How to properly trigger an insert to a linked sql server? - sql

I have the same table in two different sql servers (one is SqlServer 2000 and the other 2008).
I'm using sql server management studio.
I want that each time an insert is made on a table in the SqlServer 2000 table (Table_1) a trigger occurs and the record would also be inserted to the same table in the SqlServer 2008 table (also Table_1).
the sql server 2008 is defined as a linked server, and it is possible to run queries and perform inserts on the 2008 db from the 2000 db connection using sql server management studio.
the trigger is defined as follows :
ALTER TRIGGER [dbo].[trgrTable]
ON [dbo].[Table_1]
AFTER INSERT
AS
BEGIN
INSERT INTO [TLVSQL].[AVI_DEV].[dbo].[Table_1](ID, Value)
SELECT INSERTED.ID AS ID, INSERTED.Value AS Value
FROM INSERTED
END
the [TLVSQL].[AVI_DEV] is the 2008 db name.
But every time i perform an insert on the 2000 table i get a message that the insert failed to commit due to "sqloledb was unable to begin a distributed transaction linked server ...".
The security delegation of the linked server is well defined, i explicitly set the security credentials to a user/password of a db_owner.
What am i doing wrong ? Is there another way of doing what i ask ?
thank you.

Perform inserts from a trigger into a table on linked server - bad decision.
This will great affects on insert performance in the source table ([dbo].[Table_1])
and also there is a distributed transaction, and configuring servers
for support distributed transactions - nightmare.
One possible solution is:
On the source server you can create a synchronization queue table. For example:
CREATE TABLE dbo.SyncQueue
(
QueueId INT IDENTITY(1,1),
KeyForSync INT, -- Primary key value of record in dbo.SourceTable
SyncStatus INT -- statuses can be: 0 - New, 1 - Synchronized, 2 - Error
)
suppose you source table is
CREATE TABLE dbo.SourceTable
(
Key INT, -- primary key of the table
Data varchar(xxx)
)
Triger on dbo.SourceTable can quickly insert into dbo.SyncQueue record Key that you need synchronize
Some periodically performed stored procedure can then insert records from the queue in
table on the linked server.

Related

Best way to transfer data from source table in one db to destination table in another db daily

What would be the best way to transfer certain number of records daily from source to destination and then remove from source?
DB - SQL server on cloud.
As the databases are in the same server, you can create a job that transfers the data do the other database.
Because the databases are in the same server you can easily access them, just by adding the database before the table in the query, look the test that i did:
CREATE DATABASE [_Source]
CREATE DATABASE [_Destination]
CREATE TABLE [_Source].dbo.FromTable
(
some_data varchar(10)
)
CREATE TABLE [_Destination].dbo.ToTable
(
some_data varchar(10)
)
INSERT INTO [_Source].dbo.FromTable VALUES ('PAULO')
--THE JOB WOULD BE SOMETHING LIKE THIS:
-- INSERT INTO DESTINATION GETTING THE DATA FROM THE SOURCE
INSERT INTO [_Destination].dbo.ToTable
SELECT some_data
FROM [_Source].dbo.FromTable
-- DELETE FROM SOURCE
DELETE [_Source].dbo.FromTable

Select Scope_Identity fails on live server but not on local database

I have the following SQL statement:
insert into [Order](UserId,MembershipType,PaymentAmt,PaymentStatus,StartDate,EndDate,Status)output INSERTED.OrderId values('18','Yearly','9.99','','2017-02-14 15:13:22','2018-02-14 15:13:22','1');Select Scope_Identity()
Which will insert the data in to my dbo.Order table in my Microsoft SQL Server 2014 database locally on my PC.
But when I run this query on a live 3rd party web server (With an identical database table) I get the following error:
exception=Cannot insert the value NULL into column 'OrderId', table 'db1128212_MYDATABASE.dbo.Order'; column does not allow nulls. INSERT fails.
Why is this?
Set the OrderId column on the remote table to identity/auto increment.
Auto increment primary key in SQL Server Management Studio 2012

Most efficient way to sustain a maximum number of entries in SQL Server database table

I was wondering, what is the most efficient way of doing the following?
I'm trying to implement some sort of an auditing system where each logon to my page will be stored in a database. I use SQL Server 2005 database. The table that stores the auditing data obviously cannot grow without an upper limit. So, say, it should have a maximum of 1000 entries and then any older entries must be deleted when new ones are inserted. The question is how do you do this in a most efficient way -- do I need to add any special columns, like, say an ordinal entry number for easier clean-up?
EDIT:
Say, if the structure of my table is (pseudo code):
`id` BIGINT autoincrement
`date` DATETIME
`data1` NVARCHAR(256)
`data2` INT
How would you write this cleanup procedure?
As Tony mentioned, use dates to identify the inserts. In addition, use a clustered index on the date field, so that inserts are always at the end of the table and it is easy and efficient to scan through and delete the old rows.
If you use a number, something like this should work:
DELETE FROM myTable WHERE someField < (SELECT MAX(someField) - 1000 FROM myTable)
For a date, deleting everything older than one day would be something like:
DELETE FROM myTable WHERE someField < DateAdd('d', -1, getdate())
Do it by date not number. Have a look at your stats, see how many days 1000 is / will be. Delete anything older than that. Auditing is never particularly efficient, but if you have loads of data that doesn't help you that's very inefficient....
If I understand your needs, this should work. I've tested it on SQL 2008R2, but I can not see any reason why it would not work on SQL Server 2005.
Use a logon trigger to insert a row into your audit table.
Create an AFTER INSERT trigger on your audit table that deletes the row with MIN(ID).
Here's some code to play with:
/* Create audit table */
CREATE TABLE ServerLogonHistory
(SystemUser VARCHAR(512),
ID BIGINT,
DBUser VARCHAR(512),
SPID INT,
LogonTime DATETIME)
GO
/* Create Logon Trigger */
CREATE TRIGGER Tr_ServerLogon
ON ALL SERVER FOR LOGON
AS
BEGIN
INSERT INTO TestDB.dbo.ServerLogonHistory
SELECT SYSTEM_USER, MAX(ID)+1 , USER,##SPID,GETDATE()
FROM TestDB.dbo.ServerLogonHistory;
END
GO
/* Create the cleanup trigger */
CREATE TRIGGER AfterLogin
ON TestDB.dbo.ServerLogonHistory
AFTER INSERT
AS
DELETE
FROM TestDB.dbo.ServerLogonHistory
WHERE ID =
(SELECT MIN(ID) FROM TestDB.dbo.ServerLogonHistory);
GO;
A word of warning. If you create an invalid logon trigger, you'll not be able to logon to the database. But don't panic! It's all part of learning. You'll be able to use 'sqlcmd' to drop the bad trigger.
I did try to delete the row with the min ID in the logon trigger, but I was not able to get that to work.
Is the "ID" column a Identity column with step 1?
after you insert one row
delete column where id<IDENTITY_CURRENT(YOUR_TABLE)-1000

SQL Server 2008 - permission denied in database 'master'

I am new to SQL Server and I wanted to create my first table there.
create table Employee
(
ID smallint not null
)
I use SQL Server 2008 R2 and Windows Authentication.
when I execute , it says :
CREATE TABLE permission denied in database 'master'.
Thanks!
Seems you're trying to create the table in master database where you may not have permission to create table. However, to create your target database please follow below steps:
a. At your SQLQuery editor choose your target database (Available Database drop down list) and execute your sql query.
Or
b. Try with below statement:
USE YourTargetDatabaseName
GO
CREATE TABLE Employee ( ID SMALLINT NOT NULL)
GO
I don't think you want to create a table in the master database.
Did you create a new database first? If so, use this:
USE [MyNewDatabaseName]
GO
create table Employee ( ID smallint not null )
GO

Using SQL Server DTS Package to Conditionally Insert / Update Rows in Destination Table

I want to create a DTS Package to pull data from an Oracle table into a SQL2K
table. How can I insert rows that are not already in the SQL2K table and
update rows that already exist in the SQL2K table?
I guess I could truncate and repopulate the entire table or create a
temporary table and then do updates/inserts from the temp table into the
destination table.
Is there any easier way using DTS?
Thanks,
Rokal
You can do that in a DTS package using two data driven query tasks: one for the inserts and one for the updates. The data driven query tasks are a bit of a pain to use, but they work. I've also done this (a "merge") in sql server 2000 with an AS/400 database using a dynamic t-sql. You'd write a t-sql script that outputs psql and runs it againt a linked server to the Oracle database.
UPDATE:
A DTS "data driven query task" will let you insert|update data from the sql server connection in DTS to an oracle server connection in DTS w/o a temp table or a linked server.
Update2; here's some more info on what I mean:
http://www.databasejournal.com/features/mssql/article.php/3315951
http://msdn.microsoft.com/en-us/library/aa933507(SQL.80).aspx
Are you keeping the same primary key values?
If you are you have a number of options, some versions of SQL support the MERGE statement which will update or insert just like you require.
Or you can write your own.
Something along the lines of loading all the rows into a staging table in your SQL database and row by row checking for the existence of your primary key in your main SQL table. If the key exists update the row and if not insert it.
Yes, the primary key values in the source and destination will match.
I was hoping to accomplish this task without the use of a temporary (staging) table.
Also, I am using sql server 2000 so the MERGE statement is not available.
Try:
DELETE FROM dbo.WhateverTable WHERE WhateverTableID IN (SELECT WhateverTableID FROM MySource)
It might be pretty slow, use join instead:
Delete a
from firstTable a join secondTable b on a.id = b.id
There's no way with TSQL to do a INSERT or UPDATE in the same statement, but you could very easily do it in two statements (as you mentioned above).
Statement 1:
DELETE FROM dbo.WhateverTable
WHERE WhateverTableID IN (SELECT WhateverTableID FROM MySource)
Statement 2:
INSERT INTO dbo.WhateverTable
SELECT * FROM MySource
Also, is there any reason why you don't want to use a temp table?