I added a trigger to the table to copy the inserted data to an audit table.
I got all the column names of the table from INFORMATION_SCHEMA.
I used "SELECT * INTO #INSERTED FROM INSERTED" to copy inserted data to a temporary table.
Then used the following dynamic query to get the data from temporary table for each column.
SET #sqlText = N'SELECT ' + #ColName + ' FROM #INSERTED'
where #ColName is the column name.
It was working fine with sql server 2008.
Now we moved to sql azure. select into is not supported in sql azure. I cannot create a temporary table and then use insert on it, as my table contains over 70 columns and also, I cannot use INSERTED table for a dynamic query.
So, please suggest any solution\workaround for it.
SQL Azure V11 doesn't support select into. Please upgrade your server to SQL DB v12 and you should be able to do this.
Related
I have to take backup of a table in SQL Server, but I don't want to give specific name to the particular backup table, because in a day there could be n number of backup of that particular table because of this reason, I have to change the name of backup table, whenever we take backup. I need a query in SQL Server so that it would append date/time to the name of backup table. Query should be like below:
Select *
into TableNameBackup_DateTime from TableName
I have tried by applying below query, but it is throwing an error.
Select * into 'TableNameBackup_'+GetDate() from TableName
It can be resolved by below query
Declare #tablename AS nvarchar(80);
SET #tablename='TableNameBackup_'+
replace(replace(replace(convert(varchar(30),getdate(),121),'/','_'),':','_'),'.','_');
EXECUTE('Select * into '+ #tablename+ ' from TableName');
We have two databases one in SQL Server & one in DB2, we have a scenario where we do some data inserts & data updates and deletes in SQL Server & at the same time we also do data inserts updates & deletes in Db2.
We sync data back & forth using some processes, whenever there is a change from SQL Server we sync data to db2 for insert, update & delete, if we have a change in db2 we sync data to SQL Server, we use IBM MQ messages which we dequeue the messages to sync the changes back and forth.
Everything was good until we had some issues of data sync from Db2 to SQL Server, one of our process was down which sync from db2 to SQL Server, so there is an on demand job that runs every night that will do full data refresh from Db2 to SQL Server but we are only doing Merge Update & insert, we are not doing delete as data which is yet to be synced to db2 is also present in SQL Server, so we cannot directly delete as both databases can have more or less records, so data on SQL Server some of them are left orphan, we have a scoping so data which is getting updated in SQL Server cannot be change in db2 and vice versa.
My question is when we are syncing from Db2 to SQL Server, how to identify records that got deleted from db2 only so that we can delete those from SQL Server, we don't want to delete records that are created in SQL Server but yet to be sent to db2, we have 114 tables and we cannot maintain a flag if that is an option to differentiate.
When you said you are synchronizing data back and forth between MS SQL Server and DB2 Server, how are you capturing the changes? If using some CDC tool (IDR, GoldenGate, Informatica), these tools allow you to detect conflicts so you can decide what records to keep or delete.
If you are capturing your changes by an in-house development (triggers or your own log scraper ), you should keep at least the operation type and timestamp in your temporary change data set, so that you can recognize the operation.
If you are comparing the tables and deal with changes, you won't be able to recognize if missing columns at DB2 side represents rows deleted on DB2 side or rows added to SQL side... But you can fix that, by developing a proper change data capture mechanism.
Change tracking on the sql server side might be a viable option (as long as all the tables you would like to sync/"delete from" have a primary key).
With CT you could track which rows, for each table, were created at the sql server side
since the last sync from sql server to db2. Those rows should not be deleted yet:
DELETE
FROM SQL_SERVER_TABLE
WHERE
NOT EXISTS(SELECT * FROM CHANGETABLE())
AND NOT EXISTS(SELECT * FROM DB2_staging)
I would connect SQL to DB2 via linked servers (more there : https://learn.microsoft.com/fr-fr/sql/relational-databases/system-stored-procedures/sp-addlinkedserver-transact-sql?view=sql-server-ver15) and then do queries to find out which record are missing on both sides.
This can be accomplished with OPENQUERY. You can do something like that :
SELECT * FROM YourSqlTable
EXCEPT
SELECT * FROM OPENQUERY(YOURDB2SERVER, 'SELECT * FROM YourDB2Table')
And then the same thing inverted :
SELECT * FROM OPENQUERY(YOURDB2SERVER, 'SELECT * FROM YourDB2Table')
EXCEPT
SELECT * FROM YourSqlTable
You can then send the records on the right server .
If you have a lot of tables to compare you can write these queries with dynamic SQL
DECLARE #TABLENAME nvarchar(200);
DECLARE TABLE_CUR CURSOR FOR
SELECT TABLE_NAME FROM YourDatabaseName.INFORMATION_SCHEMA.TABLES;
OPEN TABLE_CUR
FETCH NEXT FROM TABLE_CUR INTO #TABLENAME;
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #Query nvarchar(MAX);
SET #Query = 'SELECT * FROM OPENQUERY(YOURDB2SERVER, ''SELECT *
FROM '+ #TABLENAME + ' '')
EXCEPT
SELECT * FROM '+ #TABLENAME
-- Don't forget the double '' for openquery
EXEC sp_executeSQL #Query;
SET #Query = 'SELECT * FROM '+ #TABLENAME + '
EXCEPT
SELECT * FROM OPENQUERY(YOURDB2SERVER, ''SELECT *
FROM '+ #TABLENAME + ' '')'
-- Don't forget the double '' for openquery
EXEC sp_executeSQL #Query;
END
CLOSE TABLE_CUR;
DEALLOCATE TABLE_CUR;
Thanks for the suggestions, I am not using CDC, but maintaining changes in a LOG table which are yet to be synced to DB2.
DELETE TGT
FROM [IGP].[LocationType] AS TGT
INNER JOIN #locationType SRC ON
TGT.[LocationTypeCode] = SRC.[LocationTypeCode];
I am first inserting the log table data that are yet to be synced to DB2 into #locationType temp table and delete them from IGP(staging Db2 master data) so the updates & Deletes won't be overridden from IGP staging table data which is Db2 master data.
Now I need to take care of inserts that don't exists in Db2 and there in SQL server but it's not synced from the log table I shouldn't be deleting them as it would be data loss, so I use below merge query
MERGE INTO [dbo].[LocationType] AS TGT
USING [IGP].[LocationType] AS SRC
ON TGT.[LocationTypeCode] = SRC.[LocationTypeCode]
WHEN MATCHED AND (EXISTS
(SELECT TGT.[Description] EXCEPT SELECT SRC.[Description]))
THEN
UPDATE SET TGT.[LocationTypeCode] = SRC.[LocationTypeCode],
TGT.[Description] = SRC.[Description]
WHEN NOT MATCHED THEN
INSERT([LocationTypeCode], [Description])
VALUES([LocationTypeCode], [Description])
WHEN NOT MATCHED BY SOURCE
AND (EXISTS (SELECT TGT.[LocationTypeCode]
EXCEPT SELECT [LocationTypeCode] FROM #locationType)) THEN DELETE;
I'm trying to create historic data for my company; previously i asked how to copy a table with a timestamp into the same mssql database. realistically, it dawned on me that what i really need to do is the following
1) log onto my local mssql box
2) run a query of a view (select * from view_whatever)
3) copy the results of the query and add a timestamp into another database, hosted using azure SQL
if i were doing this from the same database to another table, i'd something like this:
DECLARE #copyDate DATETIME2 = CURRENT_TIMESTAMP
INSERT INTO Hst_Opportunities
SELECT OppName, Oppvalue, #copyDate AS copyDate
FROM dbo.opportunities
the from part is what im struggling with - how do i copy cross server and database when the source database is MSSQL and the target is Azure SQL?
Based on my test, it appears you could create a linked server on your local box and insert the data using four part name:
EXEC master.dbo.sp_addlinkedserver #server = N'SQLAZURE', #srvproduct=N'sqlazure', #provider=N'SQLNCLI', #datasrc=N'NAME.database.windows.net', #catalog=N'TestDb'
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'SQLAZURE',#useself=N'False',#locallogin=NULL,#rmtuser=N'USERNAME',#rmtpassword='Password'
GO
DECLARE #copyDate DATETIME = CURRENT_TIMESTAMP;
INSERT INTO [SQLAZURE].[TestDb].[Schema].[Table]
SELECT TOP (10)
[Column1]
,[Column2]
,#copyDate AS copyDate
FROM [Localdb].[Schema].[View];
I have many different application databases with a [Log] table. I have one central database with a similar log table, but with one extra column called TenantId. There is also a Tenant table with a TenantId and a DatabaseName column. These DatabaseName contain the names of the application databases.
Now I want to loop all the application databases and copy the log entries to the central log table, with the TenantId that belongs to the application database name.
Would it be possible to write one procedure in the central database instead of creating many procedures in the application databases? All databases are on the same SQL Server instance.
Just some quick Dynamic SQL. In the example below, CHINRUS is my central database and would therefore be excluded from consolidation.
I should add, that the WHERE should be tailored to exclude any misc database on the server. Yet another option would be to maintain a table which has the proper definitions.
Declare #LogTable varchar(100)='[Chinrus].[dbo].[TransactionLog]'
Declare #CentralDB varchar(100)='Chinrus'
Declare #SQL varchar(max) = ''
Select #SQL = #SQL + SQL
From (
Select Name,SQL=';Insert Into '+#LogTable+' Select *,TenantId='''+Name+''' From ['+Name+'].[dbo].[TransactionLog] '
From master.dbo.sysdatabases
Where Name<>#CentralDB
) A
Select #SQL
--Exec(#SQL)
You can get list of all databases with following query:
SELECT name
FROM master.dbo.sysdatabases
and then you can use a cursor to get each database data and insert in one table in current database.
I have two databases, lets say Database A and B, with different datastructures.
In Database A there is a table contacts.
In Database B there is a table Accounts.
I want to transfer data from Database A table contacts to Database B table Accounts.
I am use SQL Server 2005 and want to write sql scripts to do this.
Can someone tell me what's the easiest and most efficient way to achieve this:
a) If they are on the same SQL server
b) If they are on different SQL servers.
The easiest method isn't necessarily the most efficient. SSIS is likely the most efficient, as Mitch already indicated.
The easiest (if you don't know SSIS already) is to just set up a linked server to the remote DB, and SELECT the data across using four-part naming. You set up a linked server using sp_addlinkedserver and sp_addlinkedsrvlogin (check BOL for the syntax), and query as follows:
INSERT INTO MyLocalTable (ColumnList)
SELECT <Columns> FROM RemoteServer.RemoteDB.RemoteSchema.RemoteTable
Use SSIS. It will work for both local and remote cases, and will enable you to set up a transform between the tables, to map columns to lother columns etc.
Is it a one off transfer? If it's a simple transfer I write a SELECT statement to create the INSERT statements, i.e.
SELECT 'INSERT INTO Accounts (ID, Name) VALUES (' + CAST(ID as VARCHAR) + ', ''' + Name + ''')'
FROM Contacts
Run this on Database A - and it will spit out the all INSERT statements, which you copy and paste so you can run them on Database B.
Or, on the same database:
INSERT INTO DatabaseA.dbo.Accounts (ID, Name)
SELECT Id, Name
FROM DatabaseB.dbo.Contacts
Still not happy - try setting up linked servers: http://msdn.microsoft.com/en-us/library/aa213778(SQL.80).aspx