2015-02-06 6 views
1

Я работаю над устаревшим приложением, используя базу данных Oracle 11g, и столкнулся с проблемой, когда у меня есть 5 таблиц в разных схемах с одинаковой структурой данных. Мне нужно иметь возможность вставлять данные в эти таблицы, и я пытаюсь избежать дублирования кода.Можно ли использовать переменную как имя таблицы в SQL?

Я знаю, что сделать что-то вроде следующего

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, так что я могу просто сделать одну вставку заявление, но вставить в таблицу я хочу?

+1

Пожалуйста, опишите ваши усилия и результаты до сих пор. –

ответ

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

Можете ли вы? С динамическим 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, так что вы делаете много однострочные вставки, где накладные расходы триггеров не будут ужасными, я бы, вероятно, подумал о создании представления, которое делает UNION ALL из 5 таблиц вместе с идентификатором, который сообщает вам, из какой таблицы поступают данные, и триггером 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, ...); 
... 
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(. . .) 
    . . . 
    . . .; 
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; 
Смежные вопросы