所以,基本上,我需要创建一个过程,以两个表的名称作为参数,然后创建一个新表,其中外键与参数中表的主键连接。
我需要什么:我需要这个过程来获取数据库中已经存在的两个表,找到那些受主键约束的列,创建一个表(这就是我使用
execute immediate
的原因),并引用它的 fks我的两个表的主键,这些列名称作为新创建列的数据类型,因为我们不知道参数表的 pk 列的数据类型是什么。因此,此过程应该写入已创建的表的名称或显示发生的错误(但不是 ORA)。
主要的问题是创建一个表部分,我不知道如何将这些列名放入(我希望它只是一个),我被告知我可以使用子字符串,但不知道在这种情况下我可以如何这样做,因为我不知道列名称的长度,并且我不确定有关我的列的信息是否完整且没有绑定,我应该在哪里使用它。
编辑之前写的内容,这就是我的程序全文。
create or replace procedure table_creation (table_a varchar2, table_b varchar2)
is
l_cnt_a number;
l_cnt_b number;
l_str_a varchar2 (32767);
l_str_b varchar2 (32767);
l_pk_a varchar2 (32767);
l_pk_b varchar2 (32767);
err1 exception;
err2 exception;
sql_text varchar2 (32767);
begin
SELECT count(1),
max(cols.constraint_name), listing(cols.column_name || '_1' ',')
INTO l_cnt_a, l_str_a, l_pk_a
FROM all_constraints cons
INNER JOIN all_cons_columns cols ON cons.constraint_name = cols.constraint_name
WHERE cons.table_name = table_a
AND cons.constraint_type = 'P';
IF l_cnt = 0 then
RAISE err;
END IF;
SELECT count(1),
max(cols.constraint_name), listing(cols.column_name || '_2' ',')
INTO l_cnt_b, l_str_b, l_pk_b
FROM all_constraints cons
INNER JOIN all_cons_columns cols ON cons.constraint_name = cols.constraint_name
WHERE cons.table_name = table_b
AND cons.constraint_type = 'P';
IF l_cnt = 0 then
RAISE err;
END IF;
sql_text :=
'create or replace table table_c ('
|| CHR(10)
|| 'for i in 1..l_cnt_a loop'
|| CHR(10)
|| 'column_for_a_i a_i_column%TYPE, '
|| CHR(10)
|| 'end loop'
|| CHR(10)
|| 'for i in 1..l_cnt_b loop'
|| CHR(10)
|| 'column_for_b_i b_i_column%TYPE, '
|| CHR(10)
|| 'end loop'
|| CHR(10)
|| 'constraint fk_a'
|| CHR(10)
|| 'foreign key (column_for_a_i) '
|| CHR(10)
|| 'references table_a(l_pk_a), '
|| CHR(10)
|| 'constraint fk_b'
|| CHR(10)
|| 'foreign key (column_for_b_i) '
|| CHR(10)
|| 'references table_b(l_pk_b), '
|| CHR(10)
|| ') ';
execute immediate sql_text;
dbms_output.put_line('done');
exception
when err1 then
dbms_output.put_line('first table');
when err2 then
dbms_output.put_line('second table');
end table_creation;
如果有点难以阅读,我很抱歉,我仍在学习(并希望现在问题更容易理解,如果不是 - 我会再试一次 XD
问题是您的代码生成 sql_text 作为 DDL 和 PL/SQL 的组合 - 这是行不通的。您应该创建 DDL 或 PL/SQL 动态代码。我不太明白这个问题,但我会尝试提出其中一部分的解决方案。
引用:“主要问题是创建表格部分,我不知道如何将这些列名称放入”结束引用。
您可以使用如下所示的内容生成完整的 CREATE TABLE 命令。
Select 'CREATE TABLE ' || CHR(10) || CHR(9) ||
'NEW_TABLE' || CHR(10) || CHR(9) || '(' ||
SubStr(COL_DESC, 3, Length(COL_DESC) - 4) || CHR(10) || CHR(9) ||
')' "CREATE_TABLE_DDL"
From ( Select LISTAGG(CHR(10) || CHR(9) || CHR(9) ||
Case When TABLE_NAME = 'A_TBL_1' Then COLUMN_NAME || '_FROM_T1 '
Else COLUMN_NAME || '_FROM_T2 '
End ||
Case When DATA_TYPE = 'DATE' Then DATA_TYPE || ', '
Else DATA_TYPE || '(' || DATA_LENGTH || '), '
End
) WITHIN GROUP (Order By TABLE_NAME, COLUMN_ID) "COL_DESC"
From all_tab_columns
Where TABLE_NAME IN('A_TBL_1', 'A_TBL_2')
Order By TABLE_NAME, COLUMN_ID
)
--
-- R e s u l t :
--
-- CREATE_TABLE_DDL
-- ---------------------------------------------------
-- CREATE TABLE
-- NEW_TABLE
-- ( ID_FROM_T1 NUMBER(22),
-- T2_ID_FROM_T1 VARCHAR2(20),
-- SOME_COLUMN_FROM_T1 DATE,
-- ID_FROM_T2 VARCHAR2(20),
-- T1_ID_FROM_T2 NUMBER(22),
-- SOME_OTHER_COLUMN_FROM_T2 VARCHAR2(20)
-- )
注意:我使用了 2 个虚拟表。您可以改用过程的参数并将结果存储到 sql_text 变量中。同样,您也可以生成其他 DDL 语句。