alter table adding guid column in oracle - sql

What is the statement to alter a table which holds about 10 million rows, adding a guid column which will hold a unique identifier for each row (without being part of the pk)
What datatype should the global unique identifier column be?
Is there a procedure which creates it?
How will it auto incremented or produced everytime a new record is inserted?

Break it down into the separate stages
First, we need a new column:
alter table MyTable
add guid_column raw(32) default sys_guid();
Then update the existing rows:
update MyTable
set guid_column = sys_guid();

Use identity columns feature of oracle 12c to add a column to the table which auto increments upon adding new rows to the table.
An ideal way to handle this task is to:
a) CREATE a "new" table with structure similar to the source table using CREATE TABLE AS (CTAS statement) with a new "identity column" instead of adding identity column using ALTER statement on existing table.
b) CTAS works faster compared to running ALTER on existing table.
c) After confirming that the "new" table has all the data from the source table along with an column containing unique values and all the indexes and constraints then, you can drop the original table.
Another way to avoid creating constraints, indexes present on original table onto the new table is to create an empty table with all constraints, indexes and identity column. Let DBA extract data from the original table and import it into the "new" table.
Benefits:
This approach will ensure that none of the objects dependent on the source table become INVALID which generally hampers some features of the application(s).

Related

Adding a computed column that uses MAX

I need to create a sequential number column for record number proposes
I am OK with losing sequence if I delete a row from the middle of the table
For example
1
2
3
If I delete 2, I am ok with new column been 4.
I tried to alter my table to
alter table [dbo].[mytable]
add [record_seq] as (MAX(record_seq) + 1)
but I am getting An aggregate may not appear in a computed column expression or check constraint.
Which is a bit confusing? do I need to specify an initial value? is there a better way?
If you're looking to allocate a sequence number even in cases where the table doesn't get a record inserted, I would handle it in the process responsible for performing those inserts. Create another table, in this table keep track of the max identity value of that sequence. Each time you want to perform an insert, reserve the sequence number you want by updating that table first. If you rely on selecting the max existing value, you could be at risk of multiple sessions getting the same "new" sequence number before inserting. Even if the insert fails, you will have incremented that control table so nothing else uses that value that has been reserved.
Its not supported in MsSql. You can use identity column:
ALTER TABLE [dbo].[mytable]
ADD [record_seq] INT IDENTITY
Or use trigger to update your seq column after insert and/or delete

Adding columns to existing redshift table

I have a database which contains more than 30m records, and I need to add two new columns to the database. The problem is that I need these columns to be NOT NULL, and without a default value. I thought that I would just add these columns without the NOT NULL constraint, fill them with data, then add the constraint, but Redshift doesn't support that. I have an other solution in my mind, but I wonder if there is any more simpler solution than this?
Create the two new columns with NOT NULL and DEFAULT
Filling the columns with data
Creating an empty table with the same columns as the target DB. (Of course the two new columns would be just NOT NULL)
Inserting everything from the target DB to the new DB.
Dropping the target DB
Renaming the new DB to the target.
I would suggest:
Existing Table-A
Create a new Table-B that contains the new columns, plus an identity column (eg customer_id) that matches Table-A.
Insert data into Table-B (2 columns + identity column)
Use CREATE TABLE AS to simultaneously create a new Table-C (specifying DISTKEY and SORTKEY) while querying Table-A and Table-B via a JOIN on the identity column
Verify contents of Table-C
VACCUM Table-C (shouldn't be necessary, but just in case, and it should be quick)
Delete Table-A and Table-B
Rename Table-C to desired table name (which was probably the same as Table-A)
In Summary: Existing columns in Table-A + Extra columns in Table-B ➞ Table-C
Reasoning:
UPDATE statements do not run very well in Redshift. It requires marking existing data rows for each column as 'deleted', then appending new rows to the end of each column. Doing lots of UPDATES will blow-out the size of a table and it will become unsorted. It's also relatively slow. You would need to Deep Copy or VACUUM the table afterwards to fix things.
Using CREATE TABLE AS with a JOIN will generate all "final state" data in one query and the resulting table will be sorted and in a 'clean' state
The process gives you a chance to verify the content of Table-C before committing to the switchover. Very handy for debugging the process!
See also: Performing a Deep Copy - Amazon Redshift

Can I use the same index in 2 different tables but on the same columns in Oracle

I have a table and need to create its duplicate in Oracle (including indices and sequences) as a history of the first one. To create the table with its data I can do like this:
create table new_table as select * from original_table;
Of course, this will not create any index, sequence or trigger which the original table has. Creating all that I can do in few ways. My question is not how can I create all that but my question is the following:
Since the newly created table is a copy of the original (columns are the same) can I use the same index which exists on the original table for the new one too?
An index entry points to the location of a records data at a particular location in a block. The data in your history table cannot exist in the same location as the data in the original table so therefore the locations being pointed to will never match. If you research how an index actually works in Oracle you will see why this is not possible.

Import Excel table to SQL by overwritting

I have an Excel file that maps exactly to a table in SQL Server. I have tried to import but I get the UNIQUE KEY error.
How can I overwrite the exisitng values in the database table with those in the excel file? I can convert to csv. if this is any help. Is there a statement I can write to do this?
Any guidance would be much appreciated.
Thank you
Create a second table using the same DDL as that table (in the database).
Afterward, import the Excel file into that newly created table.
Delete from the actual table (not the one just created above) all rows where the columns making up the unique key constraint match that of the the rows newly inserted into the newly created table.
Then insert into the actual table all rows that exist in the second, newly created and populated table. Because you just deleted the rows with the values you want to overwrite, you will no longer violate the unique constraint.
If you provide the column names of your table and the column(s) that make up the unique constraint I can help you write the query for #3 if needed.
Step 3 would be something like:
delete from table_name
where unique_id in
(select unique_id from newly_created_table_in_step1_and_2)
Please display the whole ERRO. if you have UNIQUE KEY Error then you have to create update query using primary key. you might have to write TSQL query.

How to create *_swap tables (w/ indexes) in postgresql

I have a students table in postgres that is populated via an external source. Each night we populate the students_swap table, and then after the long running operation is complete we rename it to students and the original table then becomes students_swap to be used the next day.
The problem with this is that when we add a new column or index to the original table we must remember to also do so on the swap table. I am attempting to automate some of this w/ the following:
-- Drop the swap table if it's already there...
DROP TABLE IF EXISTS students_swap;
-- Recreate the swap table using the original as a template...
CREATE TABLE students_swap AS SELECT * FROM students WHERE 1=2;
... populate the swap table ....
ALTER TABLE students RENAME TO students_temp;
ALTER TABLE students_swap RENAME TO ps_students;
ALTER TABLE students_temp RENAME TO students_swap;
This works well for creating the table structure but no indices are created for the swap table.
My question is how do I copy all of the indexes in addition to the table structure to make sure my original table and swap table stay in sync?
Use create table ... like instead:
CREATE TABLE students_swap (LIKE students INCLUDING ALL);
This will include indexes, primary keys and check constraints but will not re-create the foreign keys.
Edit:
INCLUDING ALL will also copy the default settings for columns populated by sequences (e.g. a column defined as serial). It sounds as if you want that. If you do not want that, then use INCLUDING INDEXES INCLUDING CONSTRAINTS instead.