SQL Server - drop multiple columns with IF EXISTS at once - sql

SQL Server supports syntax that allows to remove more than one column at a time. How to DROP multiple columns with a single ALTER TABLE statement in SQL Server?
Though it seems to be impossible to force it to work with IF EXISTS clasue for each occurence.
ALTER TABLE
DROP
| COLUMN [ IF EXISTS ]
{
column_name
} [ ,...n ]
Conditionally drops the column or constraint only if it already exists.
Example:
CREATE TABLE t(i INT, col1 INT, col2 INT);
ALTER TABLE t DROP COLUMN IF EXISTS col1, col2;
-- col1, col2 were successfully removed
ALTER TABLE t DROP COLUMN IF EXISTS col1, col2;
-- Msg 4924 Level 16 State 1 Line 1
-- ALTER TABLE DROP COLUMN failed because column 'col2' does not exist in table 't'.
Based on error message IF EXISTS takes effect only for first column.
db<>fiddle demo
Is there a limitation of this clause when combined with multiple columns at once?

The syntax is a bit cumbersome but
ALTER TABLE t DROP COLUMN IF EXISTS col1,
COLUMN IF EXISTS col2;
works fine

Related

Creating temp table from another table including partition column in hive

I am creating a temp table from another table using AS clause where I am including the partition column of another table also be part of temp table and then I am getting the below error. Below is the table create statement where col4 is the partition column of table xyz.
And while running the create statement i am getting the below error. And when I am removing the col4 from the create statement its running fine.
Error:
Error while compiling statement: FAILED: NumberFormatException For
input string: "HIVE_DEFAULT_PARTITION" (state=42000,code=40000)
Please help.
Example:
CREATE TEMPORARY TABLE abc STORED AS PARQUET AS SELECT
col1 AS col1,
col2 AS col2,
col3 AS col3,
col4 AS col4
FROM xyz;
This is a problem with source table xyz because it contains partition __HIVE_DEFAULT_PARTITION__
Hive creates a partition with value __HIVE_DEFAULT_PARTITION__ when in dynamic partition mode inserted partition value is NULL.
Partition __HIVE_DEFAULT_PARTITION__ is not compatible with numeric type and this causing error because it cannot be cast to numeric type.
To remove or query this partition, you need to change the column type to string first:
ALTER TABLE xyz PARTITION COLUMN (col4 string);
Of course you may want to backup table and check the data before removing and decide what to do with this data.
To remove partition:
ALTER TABLE xyz DROP PARTITION (col4 = '__HIVE_DEFAULT_PARTITION__');
After removing partition you can change the type of partition column back to numeric type.

postgresql insert into from select

I have two tables table1 and test_table1 which have the same schema.
Both tables have rows/data and pk id's starting from 1.
I would like to do:
insert into test_table1 select * from table1;
but this fails due to the pk values from table1 existing in test_table1.
Way around it would be to specify columns and leave the pk column out, but for some reason thats not working either:
e.g.
NOTE - no pk columns in query below
insert into test_table1 (col1, col2,..., coln) select col1,col2,...,coln from table1;
returns
ERROR: duplicate key value violates unique constraint "test_table1_pkey"
DETAIL: Key (id)=(1) already exists.
I know this works in MySql, is this just due to Postgresql? Anyway around it?
EDIT:
Both tables have primary keys and sequence set.
Since it wasn't clear - tables don't have the same data.
I would just like to add rows from table1 to test_table1.
For answers telling me to exclude primary key from the query - I did as I said before.
Just remove pk column from columns of query
insert into test_table1 (col2,..., coln) select col2,...,coln from table1;
If it still fails maybe you have not sequence on pk columns.
Create sequence on already existing pk column
create sequence test_table1_seq;
ALTER TABLE test_table1
ALTER COLUMN col1 SET DEFAULT nextval('test_table1_seq'::regclass);
And update sequence value to current
SELECT setval('test_table1_seq', (SELECT MAX(col1) FROM test_table1));
This post helped me solve my problem, not sure what went wrong:
How to fix PostgreSQL error "duplicate key violates unique constraint"
If you get this message when trying to insert data into a PostgreSQL database:
ERROR: duplicate key violates unique constraint
That likely means that the primary key sequence in the table you're working with has somehow become out of sync, likely because of a mass import process (or something along those lines). Call it a "bug by design", but it seems that you have to manually reset the a primary key index after restoring from a dump file. At any rate, to see if your values are out of sync, run these two commands:
SELECT MAX(the_primary_key) FROM the_table;
SELECT nextval('the_primary_key_sequence');
If the first value is higher than the second value, your sequence is out of sync. Back up your PG database (just in case), then run thisL
SELECT setval('the_primary_key_sequence', (SELECT MAX(the_primary_key) FROM the_table)+1);
That will set the sequence to the next available value that's higher than any existing primary key in the sequence.
You rather would want to do a UPDATE JOIN like
UPDATE test_table1 AS v
SET col1 = s.col1,
col2 = s.col2,
col3 = s.col3,
.....
colN = s.colN
FROM table1 AS s
WHERE v.id = s.id;
what you want to do is an upsert.
with upsert as (
update test_table1 tt
set col1 = t.col1,
col2 = t.col2,
col3 = t.col3
from table1 t
where t.id = tt.id
returning *
)
insert into test_table1(id, col1, col2, col3)
select id, col1,col2,col3
from table1
where not exists (select * from upsert)

Inserting data into SQL Server database with potentially duplicate data

I have two databases on different servers, which have tables called dbo.A. The data is both is largely the same, but I want to make sure both tables have the same data. I've been using SQL Server June 2016 to export data from one table to the other, but the error I get is:
Violation of PRIMARY KEY constraint ''. Cannot insert duplicate key in object A
The duplicate key value is 'Some text here'
I know I can delete the table and reinsert the rows, but that's cumbersome and pretty bad practice. What would be the best way for me to update the data in the second database?
Add the server as your linked server and use the following statement.
To add rows in TableA from say Serve B's Table A.
INSERT INTO dbo.A (Col1 , Col2 , Col3 , ....)
SELECT Col1 , Col2 , Col3 , ....
FROM [LinkedServerB].[DBName].[dbo].[A] A
WHERE NOT EXISTS ( SELECT 1 FROM dbo.A
WHERE A.PK_Column = PK_Column)
And then use the same query on Server B to add the rows from Server A
To add rows in TableA from say Serve B's Table A.
INSERT INTO dbo.A (Col1 , Col2 , Col3 , ....)
SELECT Col1 , Col2 , Col3 , ....
FROM [LinkedServerA].[DBName].[dbo].[A] A
WHERE NOT EXISTS ( SELECT 1 FROM dbo.A
WHERE A.PK_Column = PK_Column)
Ok if you can't use a linked server can you copy the data into an empty staging table. Then run the similar insert statement but use the staging table instead of the linked table

Database: Oracle Add new column but not the last column (sequence)? [duplicate]

This question already has answers here:
How to insert a column in a specific position in oracle without dropping and recreating the table?
(4 answers)
Is there a way to add column at a specified position in Oracle table? [duplicate]
(1 answer)
Closed 9 years ago.
One question
Database: Oracle
This is the stmt (Desc.: chnage type VARCHAR to CLOB)
ALTER TABLE XX
ADD (TEMP_Value CLOB);
UPDATE XX SET TEMP_Value=Value;
COMMIT;
ALTER TABLE XX DROP COLUMN Value;
ALTER TABLE XX
RENAME COLUMN TEMP_Value TO Value;
the problem:
The new clob-column is the last column in the XX table (normally).
If value second was now is the last column, How to change the sequence
I know the following solution and that is not very smart for several of columns, so I want to find a other solution.
create newtable as
select Value, X, XX,..
drop table XX;
rename newtable to XX;
Discussed here
Oracle does not support adding columns in the middle of a table, only adding them to the end, unlike MYSQL ALTER TABLE TABLENAME ADD COL1 AFTER COL2 command. 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, which would be best practice.
SELECT * FROM TABLE is not a good practice.
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 TAB1NEW 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. Remember to put back your constraints, indexes, partition... and whatever as per the original table

Referencing another column in DEFAULT definition in SQL Server 2005

I want to define a column in my table with following requirements:
The column should be insertable. If the value is provided in the INSERT statement, then it should be inserted.
If the column is not referenced in the INSERT statement, then it should be set to the sum of two other columns.
Because of the first requirement, I cannot user computed columns, since they are not insertable. Because of the second, I cannot use DEFAULT, because it doesn't allow referencing other columns in the definition. What other options do I have?
BTW, the column should be NOT NULL.
Here you go, I'm demonstrating this with an example schema since you've not provided your real table/column names.
Table:
CREATE TABLE test
(
id INT NOT NULL PRIMARY KEY IDENTITY, --made up key
col1 INT, --first column to add, wasn't sure if this was nullable or not
col2 INT, --second column to add, wasn't sure if this was nullable or not
col3 INT NOT NULL --this is the column to optionally insert into
)
Here is the trigger definition:
CREATE TRIGGER demo
ON test
INSTEAD OF INSERT
AS
INSERT INTO test (col1,col2,col3)
SELECT inserted.col1,
inserted.col2,
CASE
WHEN inserted.col3 IS NULL THEN COALESCE(inserted.col1, 0) + COALESCE(inserted.col2, 0)
ELSE inserted.col3
END
FROM inserted
Basically it replaces any insert statement done on the table with the one in the trigger, so I check using the inserted temporary table to see if the value that is trying to be inserted into our non-nullable optional column, col3, is NULL. If it is, I replace it with the addition of col1 and col2 (I'm coalescing with zero as you didn't mention if the two source columns are nullable or not).
You can then run insert statements which either include it or not, despite the fact col3 is not nullable:
INSERT INTO test(col1,col2)
SELECT 12, 31
GO
INSERT INTO test(col1, col2, col3)
SELECT 1, 2, 89
GO
Results are:
ID COL1 COL2 COL3
------------------
1 12 31 43
2 1 2 89
If the trigger wasn't there, you could have got an error trying to run that first insert statement, telling you it couldn't insert NULL into col3.
Notice also that the second insert statement that specifies a value has not been replaced by the addition, as requested.
Here's a working SQL Fiddle.