在 PL/SQL 上编写过程时遇到困难

问题描述 投票:0回答:1

所以,基本上,我需要创建一个过程,以两个表的名称作为参数,然后创建一个新表,其中外键与参数中表的主键连接。

我需要什么:我需要这个过程来获取数据库中已经存在的两个表,找到那些受主键约束的列,创建一个表(这就是我使用

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

oracle plsql procedure create-table
1个回答
0
投票

问题是您的代码生成 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 语句。

© www.soinside.com 2019 - 2024. All rights reserved.