本机动态 SQL DDL 语句未在 WHERE 子句中使用绑定变量执行
Native Dynamic SQL DDL statements not executing with bind variables in WHERE clause
我正在练习动态 SQL 和程序,以便为每周、每天和每月的仪表板实施一些脚本。这些仪表板要求我们创建 table,因此我决定坚持使用动态 SQL。
在练习这些时,我遇到了一些错误,为了模拟这些错误,我创建了以下 tables 并复制了程序。
1。生成 EMP table
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);
2。生成 EmpSalary table
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;
以下2个公式return错误:
---- 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
但我无法理解为什么会出现错误,因为在第二次尝试中,我没有为 Table 名称使用绑定变量,而在第三次尝试中,我只是简单地连接了一个变量。 .
感谢您的协助...
您的第三次尝试会成功,但您忘记了 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;
未使用绑定变量,但它仍在使用变量创建 table。
我正在练习动态 SQL 和程序,以便为每周、每天和每月的仪表板实施一些脚本。这些仪表板要求我们创建 table,因此我决定坚持使用动态 SQL。 在练习这些时,我遇到了一些错误,为了模拟这些错误,我创建了以下 tables 并复制了程序。
1。生成 EMP table
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);
2。生成 EmpSalary table
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;
以下2个公式return错误:
---- 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
但我无法理解为什么会出现错误,因为在第二次尝试中,我没有为 Table 名称使用绑定变量,而在第三次尝试中,我只是简单地连接了一个变量。 .
感谢您的协助...
您的第三次尝试会成功,但您忘记了 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;
未使用绑定变量,但它仍在使用变量创建 table。