如何解决SQL Error [946] [42000]: ORA-00946: missing TO keyword?
How to solve SQL Error [946] [42000]: ORA-00946: missing TO keyword?
我正在尝试更改所有 PK 约束名称。下面是我正在尝试的代码 运行:
BEGIN
FOR i IN (
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM ALL_CONSTRAINTS
WHERE OWNER = 'SOME_SCHEME'
AND TABLE_NAME NOT LIKE 'flyway%'
AND TABLE_NAME NOT LIKE 'BIN%'
AND CONSTRAINT_TYPE = 'P')
LOOP
dbms_output.put_line(i.CONSTRAINT_NAME || i.table_name);
EXECUTE IMMEDIATE 'ALTER TABLE i.table_name rename constraint i.constraint_name to i.table_name || ''_PK''';
END LOOP;
END;
我收到以下错误:
SQL Error [946] [42000]: ORA-00946: missing TO keyword
ORA-06512: at line 17
ORA-06512: at line 17
为什么没有却说TO不见了?
如何解决这个问题?
如果在执行之前使用 dbms_output
显示语句,您会发现它的格式不正确;无论 table 和约束是什么,您当前尝试执行的语句都是:
ALTER TABLE i.table_name rename constraint i.constraint_name to i.table_name || '_PK'
i.*
部分不是变量或值,它们实际上是那些字符串。 运行 当然,该语句手动得到相同的错误。
您需要将循环变量值连接到语句中;您还需要指定所有者,因为您正在查看 all_tables
,您不妨引用名称:
DECLARE
l_stmt varchar2(4000);
BEGIN
FOR ...
LOOP
dbms_output.put_line(i.CONSTRAINT_NAME || i.table_name);
l_stmt := 'ALTER TABLE SOME_SCHEME."' || i.table_name || '"'
|| ' rename constraint "' || i.constraint_name || '"'
|| ' to "' || i.table_name || '_PK"';
dbms_output.put_line(l_stmt);
EXECUTE IMMEDIATE l_stmt;
END LOOP;
END;
/
生成的内容更像:
ALTER TABLE SOME_SCHEME."SDO_DATUMS" rename constraint "DATUM_PRIM" to "SDO_DATUMS_PK"
我已经 hard-coded 您在循环查询中使用的 SOME_SCHEME
名称;您还可以通过将 OWNER
添加到 select 列表,然后将其连接起来(同样,引用过于谨慎)从查询本身获得它。或者在局部变量中设置它并在两个地方使用它,正如@MTO 在评论中建议的那样。
如果您只 运行 作为 SOME_SCHEME
用户,那么您可以改为查询 user_constraints
:
DECLARE
l_stmt varchar2(4000);
BEGIN
FOR i IN (
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME NOT LIKE 'flyway%' -- are these really quoted lower-case?
AND TABLE_NAME NOT LIKE 'BIN%'
AND CONSTRAINT_TYPE = 'P'
AND CONSTRAINT_NAME != TABLE_NAME || '_PK'
)
LOOP
l_stmt := 'ALTER TABLE "' || i.table_name || '"'
|| ' RENAME constraint "' || i.constraint_name || '"'
|| ' TO "' || i.table_name || '_PK"';
dbms_output.put_line(l_stmt);
EXECUTE IMMEDIATE l_stmt;
END LOOP;
END;
/
db<>fiddle 示例 tables,带引号和不带引号的标识符。
您可能还希望循环查询包括:
AND CONSTRAINT_NAME != TABLE_NAME || '_PK'
...这样您就不会触及已经具有您想要的名称模式的约束。
我正在尝试更改所有 PK 约束名称。下面是我正在尝试的代码 运行:
BEGIN
FOR i IN (
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM ALL_CONSTRAINTS
WHERE OWNER = 'SOME_SCHEME'
AND TABLE_NAME NOT LIKE 'flyway%'
AND TABLE_NAME NOT LIKE 'BIN%'
AND CONSTRAINT_TYPE = 'P')
LOOP
dbms_output.put_line(i.CONSTRAINT_NAME || i.table_name);
EXECUTE IMMEDIATE 'ALTER TABLE i.table_name rename constraint i.constraint_name to i.table_name || ''_PK''';
END LOOP;
END;
我收到以下错误:
SQL Error [946] [42000]: ORA-00946: missing TO keyword
ORA-06512: at line 17
ORA-06512: at line 17
为什么没有却说TO不见了? 如何解决这个问题?
如果在执行之前使用 dbms_output
显示语句,您会发现它的格式不正确;无论 table 和约束是什么,您当前尝试执行的语句都是:
ALTER TABLE i.table_name rename constraint i.constraint_name to i.table_name || '_PK'
i.*
部分不是变量或值,它们实际上是那些字符串。 运行 当然,该语句手动得到相同的错误。
您需要将循环变量值连接到语句中;您还需要指定所有者,因为您正在查看 all_tables
,您不妨引用名称:
DECLARE
l_stmt varchar2(4000);
BEGIN
FOR ...
LOOP
dbms_output.put_line(i.CONSTRAINT_NAME || i.table_name);
l_stmt := 'ALTER TABLE SOME_SCHEME."' || i.table_name || '"'
|| ' rename constraint "' || i.constraint_name || '"'
|| ' to "' || i.table_name || '_PK"';
dbms_output.put_line(l_stmt);
EXECUTE IMMEDIATE l_stmt;
END LOOP;
END;
/
生成的内容更像:
ALTER TABLE SOME_SCHEME."SDO_DATUMS" rename constraint "DATUM_PRIM" to "SDO_DATUMS_PK"
我已经 hard-coded 您在循环查询中使用的 SOME_SCHEME
名称;您还可以通过将 OWNER
添加到 select 列表,然后将其连接起来(同样,引用过于谨慎)从查询本身获得它。或者在局部变量中设置它并在两个地方使用它,正如@MTO 在评论中建议的那样。
如果您只 运行 作为 SOME_SCHEME
用户,那么您可以改为查询 user_constraints
:
DECLARE
l_stmt varchar2(4000);
BEGIN
FOR i IN (
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME
FROM USER_CONSTRAINTS
WHERE TABLE_NAME NOT LIKE 'flyway%' -- are these really quoted lower-case?
AND TABLE_NAME NOT LIKE 'BIN%'
AND CONSTRAINT_TYPE = 'P'
AND CONSTRAINT_NAME != TABLE_NAME || '_PK'
)
LOOP
l_stmt := 'ALTER TABLE "' || i.table_name || '"'
|| ' RENAME constraint "' || i.constraint_name || '"'
|| ' TO "' || i.table_name || '_PK"';
dbms_output.put_line(l_stmt);
EXECUTE IMMEDIATE l_stmt;
END LOOP;
END;
/
db<>fiddle 示例 tables,带引号和不带引号的标识符。
您可能还希望循环查询包括:
AND CONSTRAINT_NAME != TABLE_NAME || '_PK'
...这样您就不会触及已经具有您想要的名称模式的约束。