2

I have a tool that applies a lot of changes to a database. Many changes concern modifying column types, sizes, etc. Is there any (possibly Oracle-specific) way to tell in advance if given ALTER TABLE change will succeed and not fail because of too long values, functional indices and so on?

With non-DDL modifications this is simple: start a transaction, execute your changes and rollback. The answer is known from whether you get an exception or not. However, DDL modifications cannot be part of transactions, so I cannot follow the same procedure here.

Lalit Kumar B
  • 47,486
  • 13
  • 97
  • 124
  • 1
    If the DDL fails, an ORA-error will be associated with it. You need to retry with required changes. Modifying a table is not a regular thing, you create a table once and then you would alter it only when there is a business need and you need to go through a release so that the application is not affected. So, I wonder how would it help you to know prior to execution whether the DDL would be successful or not? If your tool is doing these modifications, then your tool should handle it programmatically. Check the type and size of the columns before altering it. – Lalit Kumar B Jun 03 '15 at 08:22
  • @LalitKumarB: I have hundreds of modifications and it would be useful to tell in advance if the change #62 is going to fail. I.e. before you even start with this. I understand I could do this programmatically, I just thought there maybe was a more robust way of asking the database itself. E.g. it is pretty non-obvious how to check for presence of functional indices on modified column or certain constraints. –  Jun 03 '15 at 08:39

3 Answers3

0

Is there any (possibly Oracle-specific) way to tell in advance if given ALTER TABLE change will succeed and not fail because of too long values

I would say it is not a good design when you need to create/modify database objects on the fly. Having said that, If the DDL fails, an ORA-error will be associated with it. You need to retry with required changes. Modifying a table is not a regular thing, you create a table once and then you would alter it only when there is a business need and you need to go through a release so that the application is not affected. So, I wonder how would it help you to know prior to execution whether the DDL would be successful or not? If your tool is doing these modifications, then your tool should handle it programmatically. Check the type and size of the columns before altering it.

If you are doing it using an external script, then you need to build your own logic. You could use the metadata views like user_tab_columns to check the data_type, data_size, data_precision, data_scale etc.

A small example of the logic to check for the size of a VARCHAR2 data type before issuing an ALTER statement(For demonstration purpose, I am doing this in PL/SQL, you could apply similar logic in your script or tool):

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.

Ok, so the table is successfully altered, lets check:

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

SQL>

I have seen few applications using groovy script which does all the check and prepares the ALTER statements based on the checks on the data_type, data_size, data_precision, data_scale etc.

For different checks, you need to add more IF-ELSE blocks. It was one example to increase the size of the VARCHAR2 data type. You need to raise exception while decreasing the column size, depending whether the column has any existing data or not...and so on...

You could create separate functions to check the metadata and return a value.

For example,

Numeric types:

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

Character types:

CREATE OR REPLACE FUNCTION is_string (i_col_name)...
<using the above logic>
IF v_type       ='VARCHAR2' THEN
<do something>
RETURN 1;
Lalit Kumar B
  • 47,486
  • 13
  • 97
  • 124
0

Two approaches come to mind, neither of which really give you what you exactly want.

The first, and I mention this purely to describe what it is you actually desire and not becuasd it is practical, is to write a tool that parses your SQL scripted changes and applies the same rules to the objects as Oracle does, i.e. alter table modify column - and check if column values do not exceed the new length. This is a huge undertaking, and when you consider that changes will be cascaded/compounded you need to cater for that too. I wouldn't expect it to be quick either - if you do a modify on a non-indexed column on a table of x million rows the tool would need to scan for data that will cause the alter to fail. Whatever internal magic Oracle uses to determine this is not going to be available to this tool.

The approach that I use, again not exactly what you want, is to clone a database from production, with cut down data. I mostly do this via scripting so that I have control, and do not rely on special permissions/dba access. I then test my deployment scripts against this, and do this iteratively until I have a clean build. I use a deployment framework I built that has restart functionality, so that if a deployment fails on step 63 of 121, it gives me a retry/skip/abort option, and if I abort it can restart from the failed step. Once I am happy with my dev build, I then test on a database that is sync'd with production - this tends to iron out problems with data and/or performance.

Now, another possible way for you might be to look at flashback. I am not sure if flashback handles DDL as well, but if it does, and assuming it is enabled on your dev/test database (a big if) then that might be an avenue worth exploring.

TenG
  • 3,843
  • 2
  • 25
  • 42
  • *Now, another possible way for you might be to look at flashback.* Flashback is post execution process and OP wants a **precheck** not post restoration. By the way, yes FLASHBACK now supports DDL statements like ALTER, given that you are on 11gR2 and up. See my answer here http://stackoverflow.com/a/25950842/3989608 – Lalit Kumar B Jun 03 '15 at 09:03
0

Try my tool CORT - www.softcraftltd.co.uk/cort

It is free and open-source. Maybe you find there what you need.

Rusty
  • 1,988
  • 10
  • 12