我正在使用Oracle 11g数据库处理遗留应用程序,并遇到了一个问题,即我有5个表都在不同的模式中,具有相同的数据结构。我需要能够将数据插入到这些表中,并且我试图避免重复的代码。
我知道做类似以下的事情
IF p_schema = SCHEMA1 THEN
INSERT INTO SCHEMA1.TABLE_NAME_SCHEMA1 (...) VALUES (...)
ELSIF p_schema = SCHEMA2 THEN
INSERT INTO SCHEMA2.TABLE_NAME_SCHEMA2 (...) VALUES (...)
ELSIF p_schema = SCHEMA3 THEN
INSERT INTO SCHEMA3.TABLE_NAME_SCHEMA3 (...) VALUES (...)
ELSIF p_schema = SCHEMA4 THEN
INSERT INTO SCHEMA4.TABLE_NAME_SCHEMA4 (...) VALUES (...)
ELSIF p_schema = SCHEMA5 THEN
INSERT INTO SCHEMA5.TABLE_NAME_SCHEMA5 (...) VALUES (...)
END IF;
有没有办法让表名成为SQL中的变量,这样我就可以只生成一个insert语句,但是插入到我想要的表中?
答案 0 :(得分:3)
p_sql_stmt := 'INSERT INTO ' || p_schema || '.TABLE_NAME (<<columns>>) ' ||
' VALUES( ?, ?, ?, ?, ?, ... ? ) ';
EXECUTE p_sql_stmt
USING val1, val2, val3, val4, ... , valN;
如果你通常都在做这类事情(而不是查看一段有这个丑陋的IF
的代码),假设你有一个基本的OLTP应用程序,这样你就可以了很多单行插入,其中触发器的开销并不会很糟糕,我可能会考虑创建一个视图来执行5个表中的UNION ALL
以及一个告诉你的标识符数据来自哪个表以及INSTEAD OF
触发器将INSERT
定向到正确的表。然后,所有其他代码都可以引用一个视图,而不是在整个地方都有IF
语句。像
CREATE VIEW composite_view
AS
SELECT 'Schema1' schema_name, a.*
FROM schema1.table_name a
UNION ALL
SELECT 'Schema2' schema_name, b.*
FROM schema2.table_name b
...
并在INSTEAD OF INSERT
触发器中
IF( :new.schema_name = 'Schema1' )
THEN
INSERT INTO schema1.table_name( <<columns>> )
VALUES( :new.col1, :new.col2, ... );
ELSIF( :new.schema_name = 'Schema2' )
THEN
INSERT INTO schema2.table_name( <<columns>> )
VALUES( :new.col1, :new.col2, ... );
...
答案 1 :(得分:2)
我认为您可以使用insert all
或insert first
。类似的东西:
INSERT FIRST
WHEN p_schema = 'SCHEMA1' THEN INTO SCHEMA1.TABLE_NAME_SCHEMA1( . . . )
WHEN p_schema = 'SCHEMA2' THEN INTO SCHEMA2.TABLE_NAME_SCHEMA2( . . . )
. . .
. . .;
答案 2 :(得分:0)
您可以使用动态sql :
declare
schema_name varchar2(50);
begin
v_name := 'SCHEMA1'; -- set the value of schema, you can do it in a loop also
execute immediate
'INSERT INTO '||schema_name ||'.TABLE_NAME_SCHEMA1 (...) VALUES (...)';
commit;
end;
答案 3 :(得分:0)
我认为处理此问题的最佳方法是使用过程,显示的用法here
CREATE OR REPLACE TYPE employeeType AS OBJECT (employeeId INT, employeeName VARCHAR2(50));
-- this is how you can use variables
CREATE TYPE ttEmployeeType AS TABLE OF employeeType;
CREATE PROCEDURE testCustom (pLocation ttEmployeeType)
AS
BEGIN
INSERT
INTO employee (emp_id, emp_name)
SELECT *
FROM TABLE(pLocation);
END;