Does Create Table as Select preserves columns order in Oracle? - sql

I'm using following statement to create a duplicate table with data. But i'm curious to know whether this statement preserves the column order of the old_table in the new_table as it is. Since i need to compare some column data of 2 tables later using MINUS statement.
CREATE TABLE new_table
AS
SELECT *
FROM old_table
Below is the minus statement used to compare. In the following statement cols are queried from ALL_TAB_COLUMNS meta data table.
SELECT COUNT(*) FROM (SELECT cols FROM old_table MINUS (SELECT cols FROM new_table))
Below is the meta data query to get column list in the order.
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = 'new_table'
SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = 'old_table'
My question, Is column order preserved in both new_table and old_table when copied using CREATE TABLE new_table AS SELECT statement mentioned above?

Yes, The New table will have columns exactly in same order as your select query.

Related

Oracle SQL: query to calculate percentage of non-null values for each column in a table

I know I can use this query to get all column names for a given table:
select column_name from all_tab_columns where table_name='my_table';
And I can use this query to calculate the percentage of non-null values for a given column in a table:
select count(col_1) / count(*), count(col_2) / count(*)
from my_table
But I want to combine these two queries to get the percentage of non-null values for all columns in a given table (without having to manually type out the column names for each table)
desired output for a given table:
column_name, completeness
col_1, 0.8
col_2, 1.0
col_3, 0.0
Is it possible to do this with only Select statements (no PL/SQL loops)?
The number of non-null values of a table is already in the data dictionary view all_tab_columns:
CREATE TABLE t AS SELECT * FROM all_objects;
EXECUTE DBMS_STATS.GATHER_TABLE_STATS(NULL, 'T');
SELECT column_name, num_nulls FROM all_tab_columns WHERE table_name='T';
COLUMN_NAME NUM_NULLS
OWNER 0
OBJECT_NAME 0
SUBOBJECT_NAME 66502
OBJECT_ID 0
DATA_OBJECT_ID 62642
...
This GATHER_TABLE_STATS analyzes the table and stores the number of null values. If you (or somebody else) inserts/deletes/updates to the table, the statistics snapshot is not exact any more, of course.
To get your "completeness" ratio, you'll need not only num_nulls, but also the number of total rows in the table. To get them, you'll need to join to the view ALL_TABLES, column NUM_ROWS, and substract NUM_ROWS - NUM_NULLS:
SELECT table_name, column_name,
t.num_rows - c.num_nulls / NULLIF(t.num_rows, 0) AS completeness
FROM all_tables t
JOIN all_tab_columns c
USING (owner, table_name);

Insert into table using select plus value?

I created a table modeled on an existing table:
CREATE TABLE new_table AS
(SELECT * FROM old_table WHERE record_status = 'xyz' ) WITH DATA;
I then added a column:
ALTER TABLE new_table ADD new_column VARCHAR(100);
I now want to select more rows from the old table into the new table, but add a fixed value (eg. 'blabla') to the new column for each row selected. I tried a bunch of things, such as:
INSERT INTO new_table
SELECT *, 'blabla'
FROM old_table)
WHERE is_blabla = 'Y'
Tried every permutation I could think of but keep getting syntax errors. Any suggestions? I'm using Teradata.
Dave
INSERT INTO new_table
SELECT old_table.*,'your_fixed_value'
FROM old_table
WHERE is_blabla='Y'
You just need to alias your table
INSERT INTO new_table
SELECT a.*,'your_fixed_value'
FROM old_table a
WHERE is_blabla='Y'

Order by tablename?

Is there any way to use the "order" function on your table name. i.e I want to union two tables then sort by the one column, then by table name.
Add constant to your column list that describes your table name, E.g.
select *, 'TableA' as TableName
from TableA
union all
select *, 'TableB' as TableName
from TableB
order by TableName
You can create a separate column (assuming that your columns are col1 and col2)
select col1,col2,table_1 as table_name
from table_1
union
select col1,col2,table_2 as table_name
from table_2
order by col1,table_name;

sql select into columns to table and columns

I have a source table that is NewID|Fruit|Apples and I need to insert those rows into target table OldID|Fruit|Apples
Is there a way to select into a new table while changing columns?
Thanks!
Try:
CREATE TABLE new_table SELECT NewID as OldID, Fruit, Apples FROM old_table
Assuming target table already exists and you want to copy all the columns
INSERT INTO target_table(OldID,Fruit,Apples)
SELECT NewID,Fruit,Apples FROM source_table

Reuse select query in a procedure in Oracle

How would I store the result of a select statement so I can reuse the results with an in clause for other queries? Here's some pseudo code:
declare
ids <type?>;
begin
ids := select id from table_with_ids;
select * from table1 where id in (ids);
select * from table2 where id in (ids);
end;
... or will the optimizer do this for me if I simply put the sub-query in both select statements?
EDIT: Here's more information about the structure of my tables.
Basically table1 is a standard table with the id being the primary key. While table2 has a 3-column primary key with id being one of those columns. In my case the id in table2 will appear in three rows.
You could use a SQL table object to store the result of the select and reuse it. It will consume more memory and will probably be efficient only if the first SELECT takes a lot of time.
CREATE TYPE tab_number IS TABLE OF NUMBER;
/
You would use it with a BULK COLLECT INTO clause:
DECLARE
ids tab_number;
BEGIN
SELECT id BULK COLLECT INTO ids FROM table_with_ids;
SELECT * /*into ??*/
FROM table1
WHERE id IN (SELECT column_value FROM TABLE(ids));
SELECT * /*into ??*/
FROM table2
WHERE id IN (SELECT column_value FROM TABLE(ids));
END;
In version 9i and before you would need to use CAST to query the table:
SELECT *
FROM table2
WHERE id IN (SELECT column_value FROM CAST (TABLE(ids) AS tab_number));
Alternatively, you could use a GLOBAL TEMPORARY TABLE to store the intermediate result set.