SQL Update across Linked Server - sql-server

I have a Linked Server set up on my host Server: "MyLinkedServer"
I have an SP on my server "HostServer".
I am calling a stored proc on HostServer that updates a table in DatabaseA on MyLinkedServer with values from a table in DatabaseB on MyLinkedServer.
I have other SPs that run fine in the same scenario, but they are doing inserts and deletes, however this SP fails to update the table in DatabaseA (no error returned, just no changed data), and if I change connections to actually run the SP on "MyLinkedServer" it works without a problem.
UPDATE MyLinkedServer.DataBaseA.dbo.MyTable
SET Column1 = db2.Column1
FROM MyLinkedServer.DataBaseA.dbo.MyTable db1
INNER JOIN
(
SELECT TOP 1 Column1
FROM MyLinkedServer.DataBaseB.dbo.MyTable db2
WHERE db2.Id = 2
) AS db2 ON db2.Id = 2
WHERE db1.Id = 1

I believe you'll need to reference the alias you reference in the from statement. Does changing
UPDATE MyLinkedServer.DataBaseA.dbo.MyTable
into
UPDATE db2
fix your issue?

Related

How to Use OpenQuery to do Create Alias (IBM DB2) in SQL Server

I use linked server to connect AS400 DB2.
For example: select query can work
select *
from openquery([DB2], 'select t1.* from lib.table01 t1
fetch first 1 rows only')
But I want to use query
Create Alias Library.T_temp For Library.T1 (MemberName)
in SQL Server.
It returned an error because it have no return rows.
As following (it will return error):
Select * from OpenQuery([DB2],' Create Alias...')
Update OpenQuery([DB2],' Create Alias...')
Is there any method to do that?
Thanks
Don't try..
Your openquery() is the preferred solution.
By using openquery(), the SQL statement is passed to Db2 and run there. Since you've included a fetch first 1 rows only only 1 row is returned.
the query form
select TOP 1 t1.*
from db2.myibmi.lib.table01 t1
offset 0 rows
first first 1 row only
Will actually pull back all rows to SQL Server, then filter them on the SQL Server.
(At least I know that's how it used when a WHERE clause was included. I assume TOP isn't any better)

Create global temporary table from result of sql code with multi joins in SAS(TSQL Code)

I have a scenario where I have several sql server data source tables. I have read only access to these sources. I cannot create permanent tables in Sql Server environment. I can however create temporary tables.
I thought of creating global temporary table out of scenario 1 result set and reference that in scenario 2(again create second global temp table in scenario 2 ) and 3rd global temp table out of third sql code. I have included generic sql below
Finally create a SAS data set out of each of these global temp tables.(We want to ensure all joins, data transformation needs to happen in sql server and not perform it in SAS)
Scenario1-
select * from table1 join table2
on table1.id=table2.id
where table1.product='Apple'
Scenario-2
Above result is then used in another query as
select * from table3 m
left join above _result_table t
on m.id=t.id
and the above result is again referenced further.
I tried researching online to find similar issue implementation and I could not find it.
I have tried below code, but this creates a SAS data set , I want to instead create a global temporary table so that another query such as below can reference it. How do I accomplish that?
proc sql ;
connect to odbc(dsn=abc user=123 pw=****** connection=shared);
create table xyz as select * from
connectoin to ODBC
(
select * from table1 join table2
on table1.id=table2.id
where table1.product='Apple'
);DISCONNECT FROM ODBC;
QUIT;
Your help is greatly appreciated.
Thanks,
Upon further research, I think I got part of the solution,-still working on creating sas data set out of temporary sql server table.
I created a temp table structure lets say ##abc,then i proceeded with following steps
PROC SQL;
CONNECT TO ODBC AS T1(DSN=SRC INSERTBUFF=32767 USER=UID PW="PD." CONNECTION=SHARED);
EXECUTE(
CREATE TABLE ##abc
(id int,
name varchar(50)
)by T1;
EXECUTE(INSERT ##abc
SELECT * FROM SqlServerTable
)by T1;
SELECT * FROM CONNECTION TO T1(SELECT * FROM ##abc);
QUIT;
I got the

How to check in UPDATE Trigger if record has really changed

I have a SQL Server 2012 UPDATE Trigger which occurs when data is updated within a table in the database (Microsoft Project Server Database) :)
I am using the following statement to get the updated element from the table within the Trigger
SELECT #dataId = INSERTED.Id FROM INSERTED;
But the problem is due to the behaviour of the Microsoft Project Server, that it updates ALL Tasks within a Project even if only one task was changed (each Task is one record in database).
I know that i can get the id of the item which should be updated, but i dont know how i could compare the to updated row with the data which is still in the database within the UPDATE Trigger?
To get what rows actually changed, then use this inside the trigger
SELECT
*
FROM
INSERTED I
JOIN
DELETED D ON I.KeyCol = D.KeyCol
WHERE
NOT EXISTS (
SELECT I.Col1, I.Col2, I.Col3, I.Col4 ...
INTERSECT
SELECT D.Col1, D.Col2, D.Col3, D.Col4 ...
)
The NOT EXISTS..INTERSECT deals with NULLs etc for you already

Verifying Syntax of a Massive SQL Update Command

I'm new to SQL Server and am doing some cleanup of our transaction database. However, to accomplish the last step, I need to update a column in one table of one database with the value from another column in another table from another database.
I found a SQL update code snippet and re-wrote it for our own needs but would love someone to give it a once over before I hit the execute button since the update will literally affect hundreds of thousands of entries.
So here are the two databases:
Database 1: Movement
Table 1: ItemMovement
Column 1: LongDescription (datatype: text / up to 40 char)
Database 2: Item
Table 2: ItemRecord
Column 2: Description (datatype: text / up to 20 char)
Goal: set Column1 from db1 to the value of Colum2 from db2.
Here is the code snippet:
update table1
set table1.longdescription = table2.description
from movement..itemmovement as table1
inner join item..itemrecord as table2 on table1.itemcode = table2.itemcode
where table1.longdescription <> table2.description
I added the last "where" line to prevent SQL from updating the column where it already matches the source table.
This should execute faster and just update the columns that have garbage. But as it stands, does this look like it will run? And lastly, is it a straightforward process, using SQL Server 2005 Express to just backup the entire Movement db before I execute? And if it messes up, just restore it?
Alternatively, is it even necessary to re-cast the tables as table1 and table 2? Is it valid to execute a SQL query like this:
update movement..itemmovement
set itemmovement.longdescription = itemrecord.description
from movement..itemmovement
inner join item..itemrecord on itemmovement.itemcode = itemrecord.itemcode
where itemmovement.longdescription <> itemrecord.description
Many thanks in advance!
You don't necessarily need to alias your tables but I recommend you do for faster typing and reduce the chances of making a typo.
update m
set m.longdescription = i.description
from movement..itemmovement as m
inner join item..itemrecord as i on m.itemcode = i.itemcode
where m.longdescription <> i.description
In the above query I have shortened the alias using m for itemmovement and i for itemrecord.
When a large number of records are to be updated and there's question whether it would succeed or not, always make a copy in a test database (residing on a test server) and try it out over there. In this case, one of the safest bet would be to create a new field first and call it longdescription_text. You can make it with SQL Server Management Studio Express (SSMS) or using the command below:
use movement;
alter table itemmovement add column longdescription_test varchar(100);
The syntax here says alter table itemmovement and add a new column called longdescription_test with datatype of varchar(100). If you create a new column using SSMS, in the background, SSMS will run the same alter table statement to create a new column.
You can then execute
update m
set m.longdescription_test = i.description
from movement..itemmovement as m
inner join item..itemrecord as i on m.itemcode = i.itemcode
where m.longdescription <> i.description
Check data in longdescription_test randomly. You can actually do a spot check faster by running:
select * from movement..itemmovement
where longdescription <> longdescription_test
and longdescription_test is not null
If information in longdescription_test looks good, you can change your update statement to set m.longdescription = i.description and run the query again.
It is easier to just create a copy of your itemmovement table before you do the update. To make a copy, you can just do:
use movement;
select * into itemmovement_backup from itemmovement;
If update does not succeed as desired, you can truncate itemmovement and copy data back from itemmovement_backup.
Zedfoxus provided a GREAT explanation on this and I appreciate it. It is excellent reference for next time around. After reading over some syntax examples, I was confident enough in being able to run the second SQL update query that I have in my OP. Luckily, the data here is not necessarily "live" so at low risk to damage anything, even during operating hours. Given the nature of the data, the updated executed perfectly, updating all 345,000 entries!

Update database table from one SQL Server database table to another?

I am trying to update database fields from one SQL Server table to another.
Our production SQL Server is [spdbprod.test.com\spprod], our QA server is [spdbQA.test.com\spQA].
I need to update table in production from QA table. I using this SQL statement but, it is giving an error.
UPDATE
[spdbprod.test.com\spprod].[aspnetdb].[dbo].[Communities_Groups] as t1
SET
t1.Show = (Select t2.show from [spdbQA.test.com\spQA].[aspnetdb].[dbo].
[Communities_Groups] as t2 where t1.GroupID = t2.GroupdID)
What I am missing here?
Error:
UPDATE. ("Incorrect syntax near the keyword 'as'.")
You are using table alias in a wrong way. You cannot do UPDATE table1 t SET field1=val, you have to write UPDATE table1 SET field=val (Or UPDATE table1 SET field=val FROM table1 t). So change your query to
UPDATE [spdbprod.test.com\spprod].[aspnetdb].[dbo].[Communities_Groups]
SET Show = t2.show
FROM [spdbprod.test.com\spprod].[aspnetdb].[dbo].[Communities_Groups] t1
INNER JOIN [spdbQA.test.com\spQA].[aspnetdb].[dbo].
[Communities_Groups] t2 ON (t1.GroupID = t2.GroupID)
I know this has been answered already but this worked for me.
Add a Linked Server under Server Objects | Linked Servers:
Microsoft documentation.
Name the Linked Server [SERVER-NAME or <some ipaddress>, <some-port>]
e.g. [10.0.0.200,2345] - I am using port 2345 but the standard MS SQL port is 1433.
Example:
We have a [Customers] table
We want to update [CustomerAddress]-field for CustomerId = 123
We want to use backup data from a server called [backupServer]
The [backupServer] is the machine where we execute the SQL
This is the SQL-code:
UPDATE production
SET
CustomerAddress = backupServer.CustomerAddress
FROM
[10.0.0.200,2345].[ProductionDatabase].[dbo].[Customers] production
INNER JOIN
[BackupDatabase].[dbo].[Customers] backupServer
ON
production.CustomerId = backupServer.CustomerId
WHERE
backupServer.CustomerId = 123
Generalized format:
UPDATE production
SET
columnName = backupServer.columnName
FROM
[SERVER-NAME or IP,PORT].[ProductionDatabase].[dbo].[tableName] production
INNER JOIN
[BackupDatabase].[dbo].[tableName] backupServer
ON
production.SomeId = backupServer.SomeId
WHERE
backupServer.SomeId = <id>
I believe you have to have a database link (linked servers) for this to work.
I do not have access to two SQL servers here at work so I cannot test it, but I sure that you need the link.
Do you have a linked server setup?
Here is a URL that may help
http://msdn.microsoft.com/en-us/library/ms188279.aspx
You need to add a Linked Server under Server Objects
You can name that Linked Server either with "CHOOSEN-NAME" or
[ipaddress , port number]
how to add a linked server using tsql , please check this link : how to find linked server
for an example purpose suppose i have named the linked server
"DESTINATION_SERVER" , database name is "DESTINATION_DB" and table
name is "DESTINATION_TBL". then from your source server your query could be like this below:
UPDATE t1
SET t1.updatecolumn = t2.updatecolumn
FROM [DESTINATION_SERVER].[DESTINATION_DB].[dbo].[DESTINATION_TBL] t1
INNER JOIN [SOURCE-SERVER].[SOURCE_DB].[dbo].
[SOURCE_TBL] t2 ON (t1.matcingcolumn = t2.matchingcolumn)

Resources