How to change lots table columns datatypes from one to another in oracle - oracle

I have a table with a lots of columns with BLOB type and I need to change it to nvarchar2.
So, to change type I can use following script:
alter table AUDIT_LOG
modify
(
column_name type_name,
column_name2 type_name2
-- etc
);
And to get all columns with given datatype I can use the following:
select column_name, 'NVARCHAR2(4000)'
from all_tab_columns
where table_name = 'TAB_NAME' and data_type = 'BLOB';
But how to join this two scripts into one?

You cannot do DML and DDL operation together in same query. You have to use dynamic SQL in a PL/SQL block
Create a variable and generate the whole alter table query in it.
Execute Immidiate
Refer this and I am sure you will be able to add rest of the logic as per your requirement.
http://www.java2s.com/Tutorial/Oracle/0440__PL-SQL-Statements/EXECUTEIMMEDIATEdynamicsqltoaltersession.htm

Related

When to specify data length on ALTER TABLE when adding a column

I am writing pl/sql code with dynamic sql statements to ALTER TABLE on table B when new columns are found in table A. When I query all_tab_columns from table a I can return all I need to do this, but in some cases it throws an error when I specify a length for the new column in table B (for example, DATE which I expected). So, I need to parse the results from all_tab_columns to include or exclude a length in the ALTER TABLE statement. On which data types should I leave off a length specification?

how to extract tables attributes like column name , datatype ,nullable for all the tables from the database from oracle pl/sql

Is there any query that can be used to retrive the Tables and its column attributes like column name , datatype, nullable etc for all the tables inside the database
For Oracle Pl/SQL
The Oracle SQL you need would be the following (run as user 'SYS'):
select owner, table_name, column_name, data_type, nullable
from dba_tab_columns;
If you do a desc dba_tab_columns you will get a list of many more columns which may be of interest to you as part of your result set.
You can use a SQL tool (i.e. SQL*Plus) to run this query or you can use PL/SQL to call this query and put the results in PL/SQL variables then print them out via DBMS_OUTPUT.PUT_LINE().
HTH

Oracle plsql ORA-39726 error

I have my plsql block as below:
DECLARE
CURSOR cdrimei IS select distinct(table_name) as tname from user_tab_columns
where column_name = 'CALLED_NUMBER_TIPO_ABONADO' and table_name not like '%_V' order by table_name;
BEGIN
FOR i in cdrimei
LOOP
execute immediate 'ALTER TABLE '||i.tname||' DROP (IMEI_CHAIN ,IMEI_STOLEN)';
execute immediate 'ALTER TABLE '||i.tname||' ADD (IMEI_CHAIN varchar2(255),IMEI_STOLEN varchar2(255))';
END LOOP;
END;
/
After executing this I am facing the below error:
ORA-39726: unsupported add/drop column operation on compressed tables
I don't understand the meaning of compressed tables.
Compressed tables have some limitations documented in the Administrator's Guide:
The following restrictions apply when adding columns to compressed tables:
Basic compression—You cannot specify a default value for an added column.
OLTP compression—If a default value is specified for an added column, then the column must be NOT NULL. Added nullable columns with default values are not supported.
The following restrictions apply when dropping columns in compressed tables:
Basic compression—Dropping a column is not supported.
OLTP compression—DROP COLUMN is supported, but internally the database sets the column UNUSED to avoid long-running decompression and recompression operations.

How do I get all records associated with a record in an aggregate root table

For testing purposes, I would like to generate an insert script for all records in all tables associated with a particular record in one of the root tables. For example, I might have a "Participant" table, which has any number of associated entries in the "Documents" table, which in turn has any number of associated entries in the "PrintRequests" table and so on and so forth. I have hundreds of these tables in the database.
Is there any way to select/script out all the records in all tables that are associated with for example ParticipantId = 1? This way, for a representative participant, I can extract all the associated records in all the tables.
One of my ideas was to restore a back up of the full database, modify all foreign key constraints to have cascade delete and then delete everything that is not participantid = 1 and let the database take care of deleting everything that is not related to the participant of interest and then script out the entire database of what remains.
For this, I might have to drop and recreate all the constraints, which I am unsure about how to do across the entire database.
Alternately, are there any other tools that would be able to do this? A migration tool for example that can take a query and only migrate the records and associated child records of that query?
While it is entirely possible to build scripts to walk through all the primary key and foreign key constraints and, via liberal use of dynamic SQL, generate these scripts, doing so would be a non-trivial undertaking. I would strongly suspect that you would be better served using a product like DataBee to generate your data subset.
You can script it creating dynamic SQL statements, but I think it is really lots of work. I think you will be faster to just find all the tables with a column "ParticipantId" with something like this
select * from all_tab_columns where column_name = 'PARTICIPANTID'
And then do some fast edit / replace / other sort of script action to generate yourself the delete statements.
Regarding the constraints. This is similar. Getting all the constraints with
SELECT owner, table_name, constraint_name
FROM dba_constraints
where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID')
You switch on and off constraints using
ALTER TABLE <table name> ENABLE/DISABLE constraint <constraint name>;
Maybe this you could do with a loop. Borrowing from this page
begin
for i in
(select constraint_name, table_name from user_constraints where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID')
) LOOP
execute immediate 'alter table '||i.table_name||' disable constraint '||i.constraint_name||'';
end loop;
end;
I am not sure about your cascading delete thing but the above gives a bit an idea how the delete would look like:
begin
for i in
(select constraint_name, table_name from user_constraints where table_name in (select table_name from all_tab_columns where column_name = 'PARTICIPANTID')
) LOOP
execute immediate 'delete from '||i.table_name||' where participantid = ''1'' ';
end loop;
end;
Hope it helps.

Alter table after keyword in Oracle

ALTER TABLE testTable ADD column1 NUMBER(1) DEFAULT 0 NOT NULL AFTER column2;
Why can't I use mySql syntax in Oracle too? The above command works in MySql. Can you give me an equivalent that works?
Error report:
SQL Error: ORA-01735: invalid ALTER TABLE option
01735. 00000 - "invalid ALTER TABLE option"
I am asking if there is any way to use after clause in Oracle command that I provided?
Because SQL is a relational algebra. It doesn't care one bit about "where" columns are located within a table, only that they exist.
To get it to work in Oracle, just get rid of the after clause. The Oracle documentation for alter table is here but it boils down to:
alter table testTable
add ( column1 number(1) default 0 not null )
There is no after clause for the alter table command.
Oracle does not support adding columns in the middle of a table, only adding them to the end. Your database design and app functionality should not depend on the order of columns in the database schema. You can always specify an order in your select statement, after all.
However if for some reason you simply must have a new column in the middle of your table there is a work around.
CREATE TABLE tab1New AS SELECT 0 AS col1, col1 AS col2 FROM tab1;
DROP TABLE tab1 PURGE;
RENAME tan1New to tab1;
Where the SELECT 0 AS col1 is your new column and then you specify other columns as needed from your original table. Put the SELECT 0 AS col1 at the appropriate place in the order you want.
Afterwards you may want to run an alter table statement on the column to make sure it's the data type you desire.
Try this :
ALTER TABLE testTable ADD column1 NUMBER(1) DEFAULT 0 NOT NULL

Resources