在我开始之前,我只想说这很糟糕。如果您正在创建自动创建数据库的脚本,我会放弃下面的查询,只使用复制/粘贴,因为这太可怕了,它不属于您的数据库部署脚本。
查询
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;
/
这是做什么的?
基本上,它会获取一个表列表并动态构建 SQL 来完成所涉及的各种任务。EXECUTE IMMEDIATE
获取我们构建 SQL 的字符串并执行它。讨厌的CHR(10)
是换行符。我想要那里的空白,因为我不知道将其遗漏会如何影响 Oracle 的解析。请注意,在几个地方,我们将表名称直接连接到其他一些文本以生成序列或 PK 约束名称。
如果您在创建过程中引用了表名并且使用了一些小写字符,这可能会或可能不会出错。如果它确实出错,请记住每条语句都涉及一次提交。错误将意味着该过程已完成一半。如果架构不是当前用户,它也会失败。(您需要在 where 子句中更改USER_TABLES
并ALL_TABLES
添加适当的过滤器,并在构建 SQL 时在表名前面添加架构以使其在另一个架构上工作。)
一个实际工作的 SQLFiddle:http ://sqlfiddle.com/#!4/b67fc/ 1(我不敢相信这实际上在 SQLFiddle 上工作。)在这种情况下,我们感兴趣的查询在模式定义中结束,因为 SQL小提琴只允许SELECT
在查询中。
祝你好运。你会需要它。不要朝自己的脚开枪。