PL / SQL存储过程创建表

时间:2016-01-22 12:35:40

标签: oracle stored-procedures plsql

我的任务是改进旧的PL / SQL和Oracle SQL遗留代码。总共大约有7000行代码!真正令我惊讶的是现有代码的一个方面是前一个编码器通过不编写任何过程或函数而不必要地创建了数百行代码 - 而编码器基本上重复了相同的代码。

例如,在现有代码中,以下SQL的重复次数为40次或更多次:

CREATE TABLE tmp_clients
AS
    SELECT * FROM live.clients;

CREATE TABLE tmp_customers
AS
    SELECT * FROM live.customers;

CREATE TABLE tmp_suppliers
AS
    SELECT * FROM live.suppliers WHERE type_id = 1;

and many, many more.....

我很想写PL / SQL,尽管我最近购买了Steven Feuerstein出版的优秀书籍“Oracle PL / SQL编程”。但是,据我所知,我应该能够编写一个可调用的过程,例如:

procedure create_temp_table (new_table_nme in varchar(60)
  source_table in varchar(60))
IS
    s_query varchar2(100);
BEGIN
    s_query := 'CREATE TABLE ' + new_table_nme + 'AS SELECT * FROM ' + source_table;
   execute immediate s_query;

EXCEPTION
    WHEN OTHERS THEN
       IF SQLCODE = -955 THEN
           NULL;
       ELSE
           RAISE;
       END IF;
END;

然后我会简单地按如下方式调用该程序:

create_temp_table('tmp.clients', 'live.clients');
create_temp_table('tmp.customers', 'live.customers');
  1. 鉴于上述问题,我提议的方法是否合理?
  2. 过程调用中的数据类型是否合理,即是否应该使用varchar2(60),还是可以强制'source_table'参数成为模式中的表名?如果表名超过60个字符,会发生什么?
  3. 我希望能够在必须以微不足道的方式限制数据的情况下传递第三个非必需参数,即处理“WHERE type_id = 1”的情况。如何修改过程以包含仅偶尔使用的参数以及如何修改其余代码。我可能会添加某种IF / ELSE语句来检查第三个参数是否为NULL,然后相应地构造s_query。
  4. 如何检查表格是否已成功创建?
  5. 我想陷入另外两个例外,即

    • 新表(例如'tmp.clients')已经存在;和
    • 源表不存在。

    EXCEPTION是否处理了这些案件?

  6. 更一般地说,从哪里可以获得SQL错误代码及其含义?
  7. 我们非常感谢您对代码的任何建议改进。

2 个答案:

答案 0 :(得分:2)

您可以使用GLOBAL临时表摆脱大量代码(逐渐!)。 立即执行并不是一种不好的做法,但如果有其他选择则应该使用它们。全局临时表在您想要提取和转换数据的位置很常见,但一旦处理完毕,您在下次加载之前就不再需要它了。每个用户只能看到他们插入的数据,不会生成重做日志。如果需要,您可以index the data加快查询速度。

像这样的东西

- 创建表

create global temporary table GT_CLIENTS
(
  id                    NUMBER(10) not null,
  Client_id             NUMBER(10) not null,
  modified_by_id        NUMBER(10),
  transaction_id        NUMBER(10),
  local_transaction_id  VARCHAR2(30) not null,
  last_modified_date_tz TIMESTAMP(6) WITH TIME ZONE not null
)
on commit preserve rows;

我建议使用on commit preserve rows选项,以便您可以调试程序并查看表中的内容。

用法是

INSERT INTO GT_CLIENTS
SELECT * FROM live.clients;

答案 1 :(得分:0)

如果这是您要采取的路径以最小化更改,那么源表不存在的错误是-942您将要停止而不是继续,因为您的临时表不会被创建。类似地,如果你已经存在一个对象就会继续存在错误会有问题,因为你不会用新数据重新加载它 - 创建失败所以表仍然有上次运行的数据。所以我肯定会更多地考虑你的异常处理程序。

那就是说,我也同意这通常不是做事的最佳方式。在多用户环境中创建和删除对象是一项灾难,如果有更合适的选项,这似乎是对资源的愚蠢浪费。