是否可以在SQL中使用变量作为表名?

时间:2015-02-06 19:30:49

标签: sql oracle11g sql-insert

我正在使用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语句,但是插入到我想要的表中?

4 个答案:

答案 0 :(得分:3)

你能吗?使用动态SQL,当然。你应该?只有5个表,我不确定动态SQL的额外复杂性是否值得。

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 allinsert 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;