我必须为很多表添加主键,并且我从stackoverflow获得了以下脚本(对于一个表):
ALTER TABLE table1 ADD ID NUMBER(12);
CREATE SEQUENCE table1Seq START WITH 1;
UPDATE table1 SET table1ID = table1Seq.NEXTVAL;
ALTER TABLE table1 ADD PRIMARY KEY (ID);
CREATE OR REPLACE TRIGGER table1PKSet
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
:NEW.ID := table1Seq.NEXTVAL;
END;
/
Run Code Online (Sandbox Code Playgroud)
但是现在我已经为用户的所有表执行了相同的操作.
所以我想知道我是否可以使用pl/sql循环用户的所有表,并执行上述操作?
在我开始之前,我只想说这是严重的.如果你正在创建自动化数据库创建的脚本,我会抛弃下面的查询,只是去复制/粘贴,因为这太可怕了,它不属于你的数据库部署脚本.
DECLARE
CURSOR TABLES IS SELECT * FROM USER_TABLES
WHERE 0 = (SELECT COUNT(*)
FROM USER_CONSTRAINTS
WHERE USER_CONSTRAINTS.TABLE_NAME = USER_TABLES.TABLE_NAME
AND USER_CONSTRAINTS.CONSTRAINT_TYPE = 'P'
);
BEGIN
FOR T IN TABLES LOOP
EXECUTE IMMEDIATE 'ALTER TABLE '||T.TABLE_NAME||' ADD ID NUMBER(12)';
EXECUTE IMMEDIATE 'CREATE SEQUENCE '||T.TABLE_NAME||'Seq START WITH 1';
EXECUTE IMMEDIATE 'UPDATE '||T.TABLE_NAME||' SET ID = '||T.TABLE_NAME||'Seq.NEXTVAL';
EXECUTE IMMEDIATE 'ALTER TABLE '||T.TABLE_NAME||' ADD PRIMARY KEY (ID)';
EXECUTE IMMEDIATE 'CREATE OR REPLACE TRIGGER '||T.TABLE_NAME||'PKSet '||CHR(10)
||'BEFORE INSERT ON '||T.TABLE_NAME||' '||CHR(10)
||'FOR EACH ROW '||CHR(10)
||'BEGIN '||CHR(10)
||':NEW.ID := '||T.TABLE_NAME||'Seq.NEXTVAL; '||CHR(10)
||'END; ';
END LOOP;
END;
/
Run Code Online (Sandbox Code Playgroud)
基本上,它获取表的列表并动态构建SQL以执行所涉及的各种任务.EXECUTE IMMEDIATE获取我们构建SQL的字符串并执行它.该CHR(10)污秽是一个换行符.我想要那里的空白,因为我不知道如何将它留下来会影响Oracle的解析.请注意,在几个地方,我们将表名直接连接到其他文本以生成序列或PK约束名称.
如果您在创建过程中引用了表名并使用了一些小写字符,则可能会出错也可能不会出错.如果它出错了,请记住每个语句都涉及提交.错误将意味着该过程完成了一半.如果架构不是当前用户,它也会失败.(你需要改变USER_TABLES,以ALL_TABLES和在where子句中添加适当的过滤器,并在表名的前面生成SQL,使其在另一个模式工作时,添加的模式.)
一个实际工作的SQLFiddle:http://sqlfiddle.com/#!4/b67fc/1 (我不敢相信这实际上对SQLFiddle起作用.)在这种情况下,我们感兴趣的查询在模式定义中已经结束,因为SQL小提琴仅允许SELECT在查询中.
祝好运.你需要它.不要用脚射击自己.