我正在练习动态SQL和过程,以便为每周,每日和每月的仪表板实现一些脚本。这些仪表板要求我们创建表,因此我决定坚持使用Dynamic SQL。 在练习这些时,我遇到了一些错误,并且为了模拟错误,我创建了下面的表并复制了这些过程。
CREATE TABLE EMP
(EMPNO NUMERIC(4) NOT NULL,
ENAME VARCHAR(10),
JOB VARCHAR(9),
MGR NUMERIC(4),
HIREDATE DATE,
SAL NUMERIC(7, 2),
COMM NUMERIC(7, 2),
DEPTNO NUMERIC(2));
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902, '17-DEC-1980', 800, NULL, 20);
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698, '20-FEB-1981', 1600, 300, 30);
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698, '22-FEB-1981', 1250, 500, 30);
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839, '2-APR-1981', 2975, NULL, 20);
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698, '28-SEP-1981', 1250, 1400, 30);
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839, '1-MAY-1981', 2850, NULL, 30);
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839, '9-JUN-1981', 2450, NULL, 10);
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566, '09-DEC-1982', 3000, NULL, 20);
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL, '17-NOV-1981', 5000, NULL, 10);
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698, '8-SEP-1981', 1500, 0, 30);
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788, '12-JAN-1983', 1100, NULL, 20);
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698, '3-DEC-1981', 950, NULL, 30);
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566, '3-DEC-1981', 3000, NULL, 20);
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782, '23-JAN-1982', 1300, NULL, 10);
CREATE TABLE empSalary
(ename varchar(20),
salary number
);
INSERT INTO empSalary VALUES ('SMITH', 2000);
INSERT INTO empSalary VALUES ('WARD', 300);
COMMIT;
以下程序适用于罚款:
----制定程序 - 尝试1
CREATE OR REPLACE PROCEDURE getData(dataType IN VARCHAR2)
IS
newTbl VARCHAR2(20);
sqlQuery VARCHAR2(100);
empName VARCHAR2(20) := 'SMITH';
BEGIN
IF dataType = 'Weekly' THEN
newTbl := 'empTblWeekly'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM emp';
EXECUTE IMMEDIATE sqlQuery;
ELSIF dataType = 'Daily' THEN
newTbl := 'empTblDaily'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM empSalary';
EXECUTE IMMEDIATE sqlQuery;
ELSIF dataType = 'Monthly' THEN
newTbl := 'empTblMonthly'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM emp WHERE ENAME = ''SMITH''';
EXECUTE IMMEDIATE sqlQuery;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found!');
COMMIT;
END;
BEGIN
getData('Monthly');
END;
SELECT *
FROM empTblMonthly21Feb;
---- Formulating a Procedure - Try 2
CREATE OR REPLACE PROCEDURE getData(dataType IN VARCHAR2)
IS
newTbl VARCHAR2(20);
sqlQuery VARCHAR2(100);
empName VARCHAR2(20) := 'SMITH';
BEGIN
IF dataType = 'Weekly' THEN
newTbl := 'empTblWeekly'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM emp';
EXECUTE IMMEDIATE sqlQuery;
ELSIF dataType = 'Daily' THEN
newTbl := 'empTblDaily'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM empSalary';
EXECUTE IMMEDIATE sqlQuery;
ELSIF dataType = 'Monthly' THEN
newTbl := 'empTblMonthly'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM emp WHERE ENAME = :empName';
EXECUTE IMMEDIATE sqlQuery USING empName;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found!');
COMMIT;
END;
BEGIN
getData('Monthly');
END;
SELECT *
FROM empTblMonthly21Feb;
---ORA-01027: bind variables not allowed for data definition operations ORA-06512: at "SYS.GETDATA", line 18 ORA-06512: at line 2
---- Formulating a Procedure - Try 3
CREATE OR REPLACE PROCEDURE getData(dataType IN VARCHAR2)
IS
newTbl VARCHAR2(20);
sqlQuery VARCHAR2(100);
empName VARCHAR2(20) := 'SMITH';
BEGIN
IF dataType = 'Weekly' THEN
newTbl := 'empTblWeekly'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM emp';
EXECUTE IMMEDIATE sqlQuery;
ELSIF dataType = 'Daily' THEN
newTbl := 'empTblDaily'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM empSalary';
EXECUTE IMMEDIATE sqlQuery;
ELSIF dataType = 'Monthly' THEN
newTbl := 'empTblMonthly'||TO_CHAR(SYSDATE, 'ddmon');
sqlQuery := 'CREATE TABLE '||newTbl||' as SELECT * FROM emp WHERE ENAME ='||empName;
EXECUTE IMMEDIATE sqlQuery;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No data found!');
COMMIT;
END;
BEGIN
getData('Monthly');
END;
SELECT *
FROM empTblMonthly21Feb;
---ORA-00904: "SMITH": invalid identifier ORA-06512: at "SYS.GETDATA", line 18 ORA-06512: at line 2
但是我无法理解错误的原因,因为在第二次尝试中,我没有使用表名的绑定变量,而在第3次尝试中我只是简单地连接一个变量......
感谢您的帮助......
答案 0 :(得分:1)
你的第三次尝试会有效,但是你忘记了sql语句中的单引号(在ename变量周围)。尝试类似:
declare
l_tabname varchar2(100) := 'MY_TAB1';
l_name varchar2(100) := 'SMITH';
l_sql varchar2(1000);
begin
l_sql := 'create table ' || l_tabname || ' as select * from emp where ename = ''' || l_name || '''';
execute immediate l_sql;
end;
没有使用绑定变量,但它仍然使用变量创建表。