我有一个工具,可以对数据库应用很多更改。许多更改都涉及到修改列类型、大小等。是否有任何(可能是特定于Oracle的)方法预先告知给定的ALTER TABLE
更改是否会成功,而不会因为值、函数索引等太长而失败?
对于非DDL修改,这很简单:启动一个事务,执行您的更改并回滚。答案可以从你是否得到一个异常中知道。但是,DDL修改不能成为事务的一部分,因此我不能在这里遵循相同的过程。
发布于 2015-06-03 08:42:13
是否有任何方法(可能是特定于Oracle的)提前告知给定的ALTER TABLE更改是否会成功,而不会因为值太长而失败
我要说的是,当您需要动态创建/修改数据库对象时,这不是一个好的设计。话虽如此,如果DDL失败,ORA-将与其关联。您需要重试所需的更改。修改表不是一件常规的事情,您只需创建一次表,然后只需在有业务需要时更改它,并且需要进行发布,以使应用程序不受影响。所以,我想知道在执行之前知道DDL是否成功会对您有什么帮助?如果你的工具正在做这些修改,那么你的工具应该以编程的方式处理它。在更改列之前,请检查列的类型和大小。
如果您使用外部脚本执行此操作,则需要构建您自己的逻辑。您可以使用像user_tab_columns这样的元数据视图来检查data_type、data_size、data_precision、data_scale等。
在发出SQLALTERSQL语句之前检查VARCHAR2数据类型大小的逻辑的一个小示例(出于演示目的,我用PL/执行此操作,您可以在脚本或工具中应用类似的逻辑):
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数据类型的大小的一个示例。您需要在减少列大小的同时引发exception,这取决于该列是否有任何现有的数据或not...and,等等...
您可以创建单独的函数来检查元数据并返回值。
例如,
数值类型:
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;
发布于 2015-06-03 08:57:38
我想到了两种方法,但这两种方法都不能给你真正想要的东西。
第一个,我提到这纯粹是为了描述它是你真正想要的,而不是因为它是实用的,是编写一个工具来解析你的SQL脚本更改,并像Oracle一样对对象应用相同的规则,即alter table modify column -并检查列值是否没有超过新的长度。这是一项巨大的任务,当您考虑到更改将是级联/复合时,您也需要迎合这一点。我也不认为它会很快--如果您对一个x百万行的表上的一个非索引列进行了修改,那么该工具将需要扫描可能导致alter失败的数据。无论Oracle使用什么内部魔法来确定这一点,该工具都无法使用。
我使用的方法也不完全是您想要的,就是从生产环境中克隆一个数据库,并减少数据。我主要通过脚本来完成这项工作,这样我就可以进行控制,而不需要依赖特殊的权限/dba访问权限。然后,我针对此测试我的部署脚本,并迭代地执行此操作,直到我有一个干净的构建。我使用我构建的具有重新启动功能的部署框架,因此,如果在121的第63步部署失败,它会给我一个重试/跳过/中止选项,如果我中止它,它可以从失败的步骤重新启动。一旦我对我的开发版本感到满意,我就会在一个与生产同步的数据库上进行测试-这往往会解决数据和/或性能方面的问题。
现在,另一种可能的方法可能是查看闪回。我不确定flashback是否也能处理DDL,但如果它能处理DDL,并且假设在您的dev/test数据库上启用了它(一个很大的假设),那么这可能是一个值得探索的途径。
发布于 2015-06-03 11:59:28
试用我的工具CORT - www.softcraftltd.co.uk/cort
它是免费的,并且是开源的。也许你能找到你需要的东西。
https://stackoverflow.com/questions/30614491
复制