【问题标题】:Is there a way to test if modifying table column will succeed in SQL?有没有办法测试修改表列是否会在 SQL 中成功?
【发布时间】:2015-08-17 07:58:32
【问题描述】:

我有一个工具可以对数据库进行大量更改。许多更改涉及修改列类型、大小等。是否有任何(可能是 Oracle 特定的)方法来提前判断给定的 ALTER TABLE 更改是否会因为值过长、功能索引等而成功而不是失败?

对于非 DDL 修改,这很简单:启动事务、执行更改并回滚。答案从你是否得到异常就知道了。但是,DDL 修改不能成为事务的一部分,所以我不能在这里遵循相同的过程。

【问题讨论】:

  • 如果 DDL 失败,将关联一个 ORA 错误。您需要重试所需的更改。修改一个表不是一件常规的事情,你创建一个表,然后你只在有业务需要时才修改它,你需要通过发布,这样应用程序才不会受到影响。所以,我想知道如何在执行之前知道 DDL 是否成功?如果您的工具正在进行这些修改,那么您的工具应该以编程方式处理它。在更改列之前检查列的类型和大小。
  • @LalitKumarB:我有数百个修改,如果更改 #62 会失败,提前告知会很有用。 IE。在你开始之前。我知道我可以以编程方式做到这一点,我只是认为可能有一种更强大的方式来询问数据库本身。例如。如何检查修改后的列或某些约束上是否存在功能索引是非常不明显的。

标签: sql oracle oracle11g ddl database-metadata


【解决方案1】:

是否有任何(可能是特定于 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;

【讨论】:

    【解决方案2】:

    我想到了两种方法,这两种方法都不能真正满足您的需求。

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

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

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

    【讨论】:

    • 现在,另一种可能的方法是查看闪回。闪回是执行后过程,OP 想要 预检查 而不是恢复后。顺便说一句,是的 FLASHBACK 现在支持像 ALTER 这样的 DDL 语句,因为您使用的是 11gR2 及更高版本。在这里查看我的答案stackoverflow.com/a/25950842/3989608
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-28
      • 2011-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-18
      • 1970-01-01
      相关资源
      最近更新 更多