Insert results of linked server into temp table from SQL Server 2016 to SQL Server 2019 - sql-server-2016

SQL Server 2016 version:
Microsoft SQL Server 2016 (SP3) (KB5003279) - 13.0.6300.2 (X64) Aug 7 2021 01:20:37 Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: )
SQL Server 2019 version:
Microsoft SQL Server 2019 (RTM-CU16) (KB5011644) - 15.0.4223.1 (X64) Apr 11 2022 16:24:07 Copyright (C) 2019 Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> (Build 17763: )
I have multiple SQL Server 2016 and SQL Server 2019 instances. I need to gather information from all the servers into one big report. One server connects to all the others via a Linked Server and runs a query to build the report. This used to work perfectly when I only had SQL Server 2016 talking to each other, but when I started trying to query SQL Server 2019, it stopped working.
I was originally doing the query through OPENQUERY but this wasn't working from SQL Server 2016 to SQL Server 2019.
I changed the query so that I could execute it like this. This query works if I execute it from SQL Server 2016.:
EXEC [LinkedServerSQL2019].msdb..sp_executesql N'SELECT top 10 event_time, action_id,
succeeded, class_type, server_principal_name,target_database_principal_name,
database_name, object_name, statement, additional_information,t.host_name,
program_name
FROM [sys].[fn_get_audit_file] (
''FilePath*.sqlaudit'',
NULL,
NULL
) t
LEFT JOIN sys.dm_exec_sessions e ON e.session_id=t.session_id
AND e.login_name = t.server_principal_name
WHERE [event_time] >= dateadd(day,-1,GETUTCDATE())
AND succeeded = 1
AND action_id = ''LGIS'' ';
But, when I try to get the results in a temp table, it stops working.
-- The Temp table is created on SQL Server 2016
CREATE TABLE #TempDump
(
event_time datetime,
action_id varchar(100),
succeeded bit,
class_type varchar(10),
server_principal_name nvarchar(max),
target_database_principal_name nvarchar(max),
database_name varchar(max),
object_name varchar(max),
statement varchar(max),
additional_information varchar(max),
host_name varchar(max),
program_name varchar(max)
)
INSERT INTO #TempDump
EXEC [LinkedServerSQL2019].msdb..sp_executesql N'SELECT top 10 event_time, action_id,
succeeded, class_type, server_principal_name,target_database_principal_name,
database_name, object_name, statement, additional_information,t.host_name,
program_name
FROM [sys].[fn_get_audit_file] (
''FilePath*.sqlaudit'',
NULL,
NULL
) t
left join sys.dm_exec_sessions e on e.session_id=t.session_id and
e.login_name=t.server_principal_name
WHERE [event_time] >= dateadd(day,-1,GETUTCDATE())
and succeeded=1 and action_id=''LGIS'' ';
I get this message:
I don't understand why I'm able to execute the query on its own, and why I can't do the Insert in a temp table?
This works when it's SQL Server 2016 to SQL Server 2016, but it doesn't when it's SQL Server 2016 to SQL Server 2019.
Any ideas?

I'm adding the solution here in case it can help someone else.
You need to set the option Enable Promotion of Distributed Transactions for RPC to FALSE in the Linked Server Properties in order for this to work.

Related

How to Select Table SQL To Oracle

I want to select data from SQL Server to Oracle (Toad Apps).
If from Oracle to SQL Server its done like this
Insert Into M_CLASSIFICATION_ORACLE
SELECT * From OPENQUERY ([B1APPS], 'select * from V_Classification_Asset' ) AS derivedtbl_1
How about in Oracle (Toad apps)?
You can able to do it by using CREATE DATABASE LINK:
Create a Database Link to connect to SQL Server:
CREATE DATABASE LINK link-name ...
Query SQL Server using the Database Link:
SELECT * FROM sqlserver-table-name#link-name;
Documentation:
https://www.oracletutorial.com/oracle-administration/oracle-create-database-link/
Calling Stored Procedure using Database Link:
https://dba.stackexchange.com/questions/1856/running-a-stored-procedure-across-db-link

How to find linked_server name in sql server management studio?

I am trying to query the following in sql server management studio:
select colname from openquery (linked_server, 'exec XX.YY.PrcName #Parameter')
When i try to give XX as linked server name i am getting an error.
Is that right or how do i find the linked_server name ?
To check linked server name :
select * from sys.sysservers
you can easily run any procedure in another server through linked server as:
exec <procedure name><parameneters> at <linked server name>
To get a list of linked servers use:
EXEC SP_LINKEDSERVERS
If you want to SELECT something from Linked server:
SELECT *
FROM [SOMESERVER\SOMEINSTANCE].somedatabase.dbo.sometable;
To EXECUTE something on linked server:
EXEC [SOMESERVER\SOMEINSTANCE].somedatabase.dbo.somestoredprocedure
SELECT *
FROM OPENQUERY([SOMESERVER\SOMEINSTANCE].somedatabase.dbo.somestoredprocedure)
More info:
sqlauthority
MSDN
You also can use sys.servers
Select * From SYS.SERVERS
When server_id = 0, this is the server name.
When server_id >0 , this is the local name of linked server.

Trigger not compatible between SQL Server 2008 and SQL Server 2012

On a version of SQL Server 2008, we have the following trigger code:
ALTER TRIGGER [dbo].[TriggerName]
ON [dbo].[SQLTable]
FOR UPDATE, INSERT
AS
SET NOCOUNT ON
IF (SELECT Count(*) FROM inserted
WHERE NOT (Column1 >= 0 AND Column1 <= 100)) > 0
BEGIN
RAISERROR 44444 ' >= 0 And <= 100'
ROLLBACK TRANSACTION
END
........
Which seems working fine on SQL Server 2008 but not anymore on SQL Server 2012. On SQL Server 2012, it's always raising an error.
When I'm updating the trigger with, it's working on SQL Server 2012
From TableName Join Inserted
If it's not supported, what is the alternative ?
Do we just have to install a SQL Server 2008 again or do we have to adapt all the SQL code ?
Is there a list with deprecated features between SQL Server 2008 and SQL Server 2012 ?
Thank you for your support

Stored procedure parameters with literals not working in SQL Server 2008 R2

I have a stored procedure that takes two parameters as varchar(50). The stored procedure does a few simple queries into a temp table and the returns the result set from the temp table (I removed the actual queries)
ALTER PROCEDURE [dbo].[cv_GetBooks]
#bookNumber as varchar(50),
#bookDate as varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--a few select statements
if #ismultiple = '0'
begin
select * from books where bookNumber = #bookNumber
and bookDate = #bookDate
and Bookname is not null
end
ELSE
Begin
select * into #temp from books
where bookNumber = #bookNumber
and bookDate = #bookDate
and Bookname is null
select * from books
where bookauthor not in (select bookauthor from #temp)
and bookNumber= #bookNumber
and bookDate= #bookDate
drop table #temp
end
END
I have this query installed on my local development machine on SQL Server 2008. I have also installed it on a two test machines running Windows Server 2003 and SQL Server 2008. The stored procedure has been working as expected.
cv_GetBooks '012345678', '06062012' --returns result set as expected
I recently moved it to a test server in another remote environment that is running Windows server 2008 and SQL Server 2008 R2. The stored procedure no longer works as expected. After running SQL Profiler I have confirmed that the same code is being executed:
cv_GetBooks '012345678', '06062012' --run on SQL server 2008 r2 returns nothing
When I removed the quotes from the query I got the expected result:
cv_GetBooks 012345678, 06062012 --run with out quotes server returns expected result set
I have since installed the same stored procedure on local version of SQL Server 2008 R2 and everything is running as expected, with the literal string quotes in place, as in the first example.
At first I thought it was an escape issue with the passed parameters but that doesn't seem correct because the passed values are do not contain any single quotes.
Having installed and had it working on so many environments, I am under the impression that this is maybe a setting in SQL Server that I am unaware of.
What could be causing the stored procedure to not return the result set with the string literals in place on the SQL Server 2008 r2 instance, but work correctly with out them there?
You did not post the table definition of table Books, but
cv_GetBooks '012345678', '06062012'
--run on SQL server 2008 r2 returns nothing
cv_GetBooks 012345678, 06062012
--run with out quotes server returns expected result set
could be caused if BookNumber and BookDate were numeric rather than varchar:
Leading zero in ints is dropped, and when converted to varchar the resulting string does not contain the leading zero.
It's also not clear how the data in your table affects the execution (IF statement!) in your code.
This might not be the exact answer, but try this as a way to finding out more about the problem. Run some basic queries (not the whole proc) in SSMS, with the parameters in place, such as:
(I'm not sure where #ismultiple comes from - doesn't seem to be declared or parameterised?)
select *
from books
where bookNumber = '012345678'
and bookDate = '06062012'
and Bookname is null
and
select *
from books
where bookNumber = 012345678
and bookDate = 06062012
and Bookname is null
Do you get the same results? What results do you get?
My suspicion is the data types: Somewhere something is being converted, and therefore not working in one environment but working in another (where the data type is different or the SQL version doesn't convert automatically). EG: 012345678 could be being converted to 12345678 if the data is stored in the table as a numeric data type. But try and isolate the behaviour without the stored procedure and/or the temp table, that might help narrow the possible causes down...

Using 4-part naming to do insert to DB2 from SQL Server 2005?

We're using DB2 9.1 on Linux and SQL Server 2005, and the IBM db2 odbc driver. We have a linked server set up to DB2. From SQL Server, I can do the following:
-- I can create the new table fine
exec ('create table dev.TestSylviaB (field1 int) in TS_DEV_USER_XXXX')
at LinkDB2
-- I can use 4 part naming to select from it, as long as I skip the second part and put everything in upper case
select * from LINKDB2..DEV.TESTSYLVIAB
-- I can insert using Exec (which does pass through)
exec ('insert into DEV.TestSylviaB (field1 ) values (1)') at LinkDB2
-- HOWEVER I cannot insert via the standard 4 part naming, like this:
insert into LINKDB2..DEV.TESTSYLVIAB values (1)
I get a "driver not capable" error message:
OLE DB provider "MSDASQL" for linked server "LINKDB2" returned message "[IBM][CLI Driver] CLI0150E Driver not capable. SQLSTATE=S1C00".
Msg 7343, Level 16, State 2, Line 1
The OLE DB provider "MSDASQL" for linked server "LINKDB2" could not INSERT INTO table "[LINKDB2]..[DEV].[TESTSYLVIAB]".
Any thoughts?
thanks!
Sylvia
The 4 part name insert is a distributed transaction and the DB2 driver needs to enroll into it. See Registering the IBM DB2 Driver for ODBC and CLI with the Microsoft DTC.