有没有办法测试修改表列是否会在SQL中成功?

时间:2015-06-03 08:17:34

标签: sql oracle oracle11g ddl database-metadata

我有一个工具可以对数据库进行大量更改。许多更改都涉及修改列类型,大小等。是否有任何(可能是Oracle特定的)方法事先告知给定的ALTER TABLE更改是否会成功并且由于值太长,功能索引等而不会失败?

通过非DDL修改,这很简单:启动事务,执行更改和回滚。答案可以从你是否得到例外中得知。但是,DDL修改不能成为事务的一部分,所以我不能在这里遵循相同的过程。

3 个答案:

答案 0 :(得分:0)

  

是否有任何(可能是Oracle特定的)方式事先告知如果给定的ALTER TABLE更改将成功并且由于值太长而不会失败

我想说当你需要动态创建/修改数据库对象时,这不是一个好的设计。话虽如此,如果 DDL 失败, ORA-error 将与之关联。您需要重试所需的更改。修改表格不是一件常规的事情,您只需创建一个表格,然后只有在有业务需求时才需要更改它,并且需要通过发布版本以便应用程序不受影响。所以,我想知道在执行之前你是否会知道DDL是否会成功?如果您的工具正在进行这些修改,那么您的工具应该以编程方式处理它。在更改列之前检查列的类型和大小。

如果您使用外部脚本进行此操作,则需要构建自己的逻辑。您可以使用 user_tab_columns 等元数据视图来检查 data_type,data_size,data_precision,data_scale 等。

在发出 ALTER 语句之前检查 VARCHAR2 数据类型大小的逻辑的一个小例子(出于演示目的,我在PL /中执行此操作SQL,您可以在脚本或工具中应用类似的逻辑):

SQL> CREATE TABLE t (A VARCHAR2(10));

Table created.

SQL> DESC t;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  VARCHAR2(10)

SQL> SET serveroutput ON
SQL> DECLARE
  2    v_type   VARCHAR2(20);
  3    v_size   NUMBER;
  4    new_size NUMBER;
  5  BEGIN
  6    new_size:= 20;
  7    SELECT data_type,
  8      data_length
  9    INTO v_type,
 10      v_size
 11    FROM user_tab_columns
 12    WHERE table_name='T';
 13    IF v_type       ='VARCHAR2' THEN
 14      IF new_size   > v_size THEN
 15        EXECUTE IMMEDIATE 'ALTER TABLE T MODIFY A '||v_type||'('||new_size||')';
 16        DBMS_OUTPUT.PUT_LINE('Table altered successfully');
 17      ELSE
 18        DBMS_OUTPUT.PUT_LINE('New size should be greater than existing data size');
 19      END IF;
 20    END IF;
 21  END;
 22  /
Table altered successfully

PL/SQL procedure successfully completed.

好的,所以表格成功改变了,让我们检查:

SQL> DESC t;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  VARCHAR2(20)

SQL>

我见过很少有使用 groovy 脚本的应用程序,它根据对data_type,data_size,data_precision,data_scale等的检查执行所有检查并准备 ALTER 语句。

对于不同的检查,您需要添加更多 IF-ELSE 块。这是增加 VARCHAR2 数据类型的大小的一个示例。您需要在减小列大小时引发异常,具体取决于该列是否包含现有数据 ...等等。

您可以创建单独的功能来检查元数据并返回值。

例如,

数字类型:

CREATE OR REPLACE FUNCTION is_numeric (i_col_name)...
<using the above logic>
IF v_type       ='NUMBER' THEN
<do something>
RETURN 1;

字符类型:

CREATE OR REPLACE FUNCTION is_string (i_col_name)...
<using the above logic>
IF v_type       ='VARCHAR2' THEN
<do something>
RETURN 1;

答案 1 :(得分:0)

我想到了两种方法,它们都没有真正为您提供您想要的东西。

第一个,我提到这纯粹是为了描述你真正想要的东西而不是实用的,就是编写一个工具来解析你的SQL脚本化的变化,并将相同的规则应用到对象,就像Oracle一样,即alter table modify column - 并检查列值是否超过新长度。这是一项艰巨的任务,当您考虑更改将进行级联/复合时,您也需要满足这一需求。我也不希望它快速 - 如果你对x百万行的表上的非索引列进行修改,工具将需要扫描导致alter失败的数据。无论Oracle使用什么内部魔法来确定这个,这个工具都无法使用。

我使用的方法,再次不是你想要的,是从生产中克隆数据库,减少数据。我主要通过脚本执行此操作,以便我可以控制,并且不依赖于特殊权限/ dba访问。然后我针对此测试我的部署脚本,并迭代地执行此操作,直到我有一个干净的构建。我使用我构建的具有重启功能的部署框架,因此如果部署在121的步骤63中失败,它会给我一个重试/跳过/中止选项,如果我中止,它可以从失败的步骤重新启动。一旦我对我的开发构建感到满意,我就会测试一个与生产同步的数据库 - 这往往会消除数据和/或性能方面的问题。

现在,另一种可能的方法是查看闪回。我不确定闪回是否也处理DDL,但如果确实如此,并假设它在你的开发/测试数据库上启用(一个很大的if)那么这可能是一个值得探索的途径。

答案 2 :(得分:0)

试试我的工具CORT - www.softcraftltd.co.uk/cort

它是免费和开源的。也许你找到了你需要的东西。