How to treat unique constraint violations in a data migration script? - sql-server

Here I'm trying to migrate some data from a table column to a brand new table in which destination column have an unique constraint. Basically I'm trying to:
INSERT INTO FooTable VALUES (SELECT BarTable.Code FROM BarTable)
FooTable have only 2 columns: ID and Code (column with unique constraint).
But on BarTable.Code, maybe there are some duplicate values that I need to treat and fit them in the new constraint (maybe: Code = Code + 1 or else).
Any ideas on how to do that?
I am using MS SQL Server 2008 R2.
Thank you in advance.

You can use the MERGE command and insert a different record when the codes match.
Here is an example based on your scenario:
MERGE FooTable AS T
USING BarTable AS S
ON (T.Code = S.Code)
WHEN NOT MATCHED BY TARGET
THEN INSERT(Code) VALUES(S.Code)
WHEN MATCHED
THEN INSERT(Code) VALUES(S.Code+1)

You can use Not Exists
INSERT INTO FooTable VALUES (SELECT distinct br.Code FROM BarTable br where NOT EXISTS(SELECT * FROM FooTable bs where br.code=bs.code ) )

Related

create table and assign table names from a select query in sqlite

I have a select query that returns a single column. Is there a way in sqlite to create a new table using the results as column names?
I tried this but it did not work.
CREATE TABLE newTable (SELECT nameCol FROM oldTable);
SQLite does not support dynamic SQL so this is not possible.
The best that you can do is construct the SQL statement that you can use to create the table by using your preferred programming language:
SELECT 'CREATE TABLE newTable (' ||
(SELECT GROUP_CONCAT(nameCol) FROM oldTable) ||
');' AS sql;
The above query returns 1 row with 1 column with a string like:
CREATE TABLE newTable (column1,column2,column3);
See a simplified demo.

Unique entries over to tables in database

I have a problem where I need to check that two columns in each table in a database are unique.
We have the database with barcode entries called uid and rid.
Table 1: T1.uid
And
Table 2: T2.rid
No barcodes in the two table columns must be the same.
How can we ensure that.
If a insertion of a barcode into table T1.uid matches an entry in
T2.rid we want to throw an error.
The tables are cleaned up and is in a consistent state where the entries in
T1.uid and T2.rid are unique over both table columns.
It is not possible to insert NULL values in the tables respective uid and tid column(T1.uid and T2.rid)
It is not possible to create a new table for all barcodes.
Because we don't have full control of the database server.
EDIT 19-02-2015
This solution cannot work for us, because we cannot make a new table
to keep track of the unique names(see table illustration).
We want to have a constraint over two columns in different tables without changing the schema.
Per the illustration we want to make it impossible for john to exist in
T2 because he already exists in table T1. So an error must be "thrown"
when we try to insert John in T2.Name.
The reason is that we have different suppliers that inserts into these tables
in different ways, if we change the schema layout, all suppliers would
need to change their database queries. The total work is just to much,
if we force every suppplier to make changes.
So we need something unobtrusive, that doesnt require the suppliers to change
their code.
A example could be that T1.Name is unique and do not accept NULL values.
If we try insert an existing name, like "Alan", then an exception will occur
because the column has unique values.
But we want to check for uniqueness in T2.Name at the same time.
The new inserted value should be unique over the two tables.
Maybe something like this:
SELECT uid FROM Table1
Where Exists (
SELECT rid FROM Table2
WHERE Table1.uid = rid )
This will show all rows from Table1 where their column uid has an equivalent in column rid of Table2.
The condition before the insertion happens could look like below. #Idis the id you need to insert the data for.
DECLARE #allowed INT;
SELECT #allowed = COUNT(*)
FROM
(
SELECT T1.uid FROM T1 WHERE T1.uid = #Id
UNION ALL
SELECT T2.rid FROM T2 WHERE T2.rid = #id
)
WHERE
#id IS NOT NULL;
IF #allowed = 0
BEGIN
---- insert allowed
SELECT 0;
END
Thanks to all who answered.
I have solved the problem. A trigger is added to the database
everytime an insert or update procedure is executed, we catch it
check that the value(s) to be inserted doens't exist in the columns of the two
tables. if that check is succesfull we exceute the original query.
Otherwise we rollback the query.
http://www.codeproject.com/Articles/25600/Triggers-SQL-Server
Instead Of Triggers

how to update table(new_DB) from old table(old_DB)

What I have:
1 table(table is in both DB's)
2 databases(currently used + archived from last year(old))
"ID" is the primary key for the table.
my issue:
archived database table has rows in it that is not present in the currently used database table. Can anyone tell me how I go about updating the currently used database table from the old database table(i.e. insert * unique rows from old database table into new database table)
It sounds simple enough but wanted some advice before proceeding as I DO NOT want duplicate rows, I just want to throw the rows in the old table(that IS NOT present in the currently used database table) into the new one(copy only is fine).
I hope I explained clearly enough.
Insert rows from the new table only if row with same id not exists in old table:
insert into old_table select * from new_table nt
where not exists (select 1 from old_table
where id = nt.id)
(Specifying columns, both inserted and selected, is nice - but I'm lazy here...)
You can usually address tables from other databases by prefixing the database name: new_db.foo_table or old_db.foo_table. This way you can look for rows in the old table that have no duplicates in the new table:
select *
from old_db.foo_table as old_foo
where not exists (
select 1
from new_db.foo_table as new_foo
where new_foo.key_field = old_foo.key_field
-- add more comparisons as needed
);
Then you can use the insert into new_db.foo_table select ... syntax to put the records into the new table.
Use LEFT JOIN filtering NULLs in target table. I think it will be faster
INSERT INTO NEW_TABLE
SELECT ot.* FROM OLD_TABLE ot
LEFT JOIN NEW_TABLE nt on ot.ID = nt.ID
WHERE nt.ID IS NULL

Copy missing rows from one table to another with multi-column primary key

This topic is related to Copy missing rows from one table to another in sql server with stored procedure but this time the problem is a bit more complex.
I have to tables in different databases (on the same server) that are identical. I need to transfer the data rows from the left database table to the right database table, but I only want to transfer the rows that aren't in the right database table already.
My table have four primary keys, see image
I'd like to use something like this
insert into [EXTERN_EPI6R2].[dbo].[tblBigTableReference]
select * from [EXTERN].[dbo].[tblBigTableReference]
where (
pkId not in (select pkId
from [EXTERN_EPI6R2].[dbo].[tblBigTableReference])
and PropertyName not in (select PropertyName
from [EXTERN_EPI6R2].[dbo].[tblBigTableReference])
and IsKey not in (select IsKey
from [EXTERN_EPI6R2].[dbo].[tblBigTableReference])
and [Index] not in (select [Index]
from [EXTERN_EPI6R2].[dbo].[tblBigTableReference])
)
But, that wont work since the stacking of the conditions is wrong in some way.
Im using SQL Server 2008 R2
Your query is not correct because your various conditions can be matched on different rows.
insert into [EXTERN_EPI6R2].[dbo].[tblBigTableReference]
select * from [EXTERN].[dbo].[tblBigTableReference] AS s
where NOT EXISTS
(
SELECT 1 FROM [EXTERN_EPI6R2].[dbo].[tblBigTableReference] AS d
WHERE d.pkId = s.pkId
AND d.PropertyName = s.PropertyName
AND d.IsKey = s.IsKey
AND d.[Index] = s.[Index] -- terrible column name
);
But this begs the question - why are all four of these columns part of the key? Is pkId not enough? If it isn't, it sure has a strange and incorrect name.

Merge query in SQL Server 2008

I having the scenario of loading the data from source table to target table. If the data from source is not present in target, then i need to insert. If it is present in the target table already, then update the status of the row to 'expire' and insert the column as new row. I used Merge query to do this. I can do insert if not exists and i can do update also. But while trying to insert when matched, it says insert not allowed in 'when matched' clause.
Please help me.. Thanks in advance
If you want to perform multiple actions for a single row of source data, you need to duplicate that row somehow.
Something like the following (making up table names, etc):
;WITH Source as (
SELECT Col1,Col2,Col3,t.Dupl
FROM SourceTable,(select 0 union all select 1) t(Dupl)
)
MERGE INTO Target t
USING Source s ON t.Col1 = s.Col1 and s.Dupl=0 /* Key columns here */
WHEN MATCHED THEN UPDATE SET Expired = 1
WHEN NOT MATCHED AND s.Dupl=1 THEN INSERT (Col1,Col2,Col3) VALUES (s.Col1,s.Col2,s.Col3);
You always want the s.Dupl condition in the not matched branch, because otherwise source rows which don't match any target rows would be inserted twice.
From the example you posted as a comment, I'd change:
MERGE target AS tar USING source AS src ON src.id = tar.id
WHEN MATCHED THEN UPDATE SET D_VALID_TO=#nowdate-1, C_IS_ACTIVE='N', D_LAST_UPDATED_DATE=#nowdate
WHEN NOT MATCHED THEN INSERT (col1,col2,col3) VALUES (tar.col1,tar.col2,tar.col3);
into:
;WITH SourceDupl AS (
SELECT id,col1,col2,col3,t.Dupl
FROM source,(select 0 union all select 1) t(Dupl)
)
MERGE target AS tar USING SourceDupl as src on src.id = tar.id AND Dupl=0
WHEN MATCHED THEN UPDATE SET D_VALID_TO=#nowdate-1, C_IS_ACTIVE='N', D_LAST_UPDATED_DATE=#nowdate
WHEN NOT MATCHED AND Dupl=1 THEN INSERT (col1,col2,col3) VALUES (src.col1,src.col2,src.col3);
I've changed the values in the VALUES clause, since in a NOT MATCHED branch, the tar table doesn't have a row to select values from.
Check out one of those many links:
Using SQL Server 2008's MERGE Statement
MERGE on Technet
Introduction to MERGE statement
SQL Server 2008 MERGE
Without actually knowing what your database tables look like, we cannot be of more help - you need to read those articles and figure out yourself how to apply this to your concrete situation.

Resources