Linked servers, results query xp_cmdshell to table migration SQL Server 2005 to SQL Server 2019 - sql

I'm migrating procedures from Microsoft SQL Server 2005 to Microsoft SQL Server 2019 and I got stuck while trying insert query result xp_cmdshell in linked servers to table
I'm out of ideas
Old solution in Microsoft SQL Server 2005:
INSERT INTO LOGTABLE (ShopNo,Line) SELECT 1, OUTPUT FROM openquery ([IP_LINKED_SERV],'set fmtonly off; exec master..xp_cmdshell ''type d:\log\file.log'' ')
Microsoft SQL Server 2019 gives me error:
Msg 11519, Level 16, State 1, Procedure
sp_describe_first_result_set, Line 1 [Batch Start Line 0] The metadata could not be determined because statement 'exec master..xp_cmdshell 'type d:\log\file.log'' invokes an extended stored procedure.`
I found a way how to do xp_cmdshell in SQL Server 2019 at linked servers
EXEC ('set fmtonly off;exec master..xp_cmdshell ''type d:\log\file.log'' ') AT [IP_LINKED_SERV]
However I can't insert this results in table
INSERT INTO LOGTABLE (ShopNo,Line) SELECT '998', OUTPUT FROM EXEC ('set fmtonly off;exec master..xp_cmdshell ''type d:\log\file.log'' ') AT [IP_LINKED_SERV]
Incorrect syntax near the keyword 'EXEC'.
part of the procedure in sql2005:
DECLARE TableCursor CURSOR FOR
SELECT IP, SqlUser, SqlPass, Object FROM ..ObjectInfo
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO #Ip, #SqlUser, #SqlPass, #Object
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #Object
SELECT #PARAMS = ' #tmp_object varchar(5) OUTPUT'
set #SQL = 'INSERT INTO LOGTABLE (Object,Line) SELECT #tmp_object, output FROM openquery (['+#Ip+'],''set fmtonly off;
exec master..xp_cmdshell ''''type d:\log\file.log''''
'')'
BEGIN TRY
EXECUTE sp_executesql #SQL,#PARAMS, #tmp_object = #Object OUTPUT
END TRY
BEGIN CATCH
INSERT INTO LOGTABLE (Object, Line) VALUES(#Object, '-error')
END CATCH```

Related

Using openrowset in SQL Server 2014

I have the below SQL statement that I was using to get data from a stored procedure into a temp table
SET #sql = N'SELECT * INTO #CustomTable3HTML
FROM
OPENROWSET(''SQLNCLI'',''Server='+ ##SERVERNAME +';UID='+#UserName+';PWD='+#Password+';Database=SalesDeals'',
''SET NOCOUNT ON;SET FMTONLY OFF;EXEC dbo.prGetDealProposalDetail ''''' + #DealID + ''''',''''' + #FeeType +''''''')
'
EXEC sp_executesql #sql
This was working fine in SQL Server 2008, but after the server got upgraded to SQL Server 2014, I started getting this error:
The metadata could not be determined because statement 'Insert #TempDetail exec prExcelCalculations_GetPricingSummary #Dealno,'FSA'' in procedure 'prGetDealProposalDetail' uses a temp table.
Which is because in the stored procedure I call in the Openrowset calls another procedure and uses temp tables..The columns are dynamic.
Can someone please let me know what can I do to fix it?

Execute openrowset stored procedure, parameter use

Little bit of background information:
I have a stored procedure, lets call it SP1. SP1 calls another stored procedure: SP2. SP2 calls another stored procedure: SP3.
Now, the first stored procedure (SP1) returns a resultset. The resultset are parameters for SP2, this is done with a cursor.
Because of these nested inserts and executes, i have to use an openrowset dynamic SQL string to execute my stored procedures.
This is my query:
DECLARE #P_Source varchar(255) = 'test'
DECLARE #P_Location varchar(255) = 'test'
DECLARE #sql varchar(max)
SET #sql = 'INSERT INTO #tmp
SELECT *
FROM OPENROWSET (
''SQLOLEDB'',
''Server=(local);TRUSTED_CONNECTION=YES;'',
''set fmtonly off
EXECUTE dbo.SP1
#P_Source = '''''+#P_Source+'''''''
,#P_Location = '''''+#P_Location+'''''''
)'
exec(#sql)
(I have ofcourse created the table #tmp). I have more parameters to be exact (12), all varchar, but I left them out to not make it messy.
I'm getting the following error
Msg 102, Level 15, State 1, Line 12
Incorrect syntax near ','.
am I using the openrowset command in the correct way with the corresponding procedure parameters?
All those quotes get confusing. By doing select #sql prior to the exec you can see what SQL Server is going to try and do. Based on the query you've provided #sql currently contains:
INSERT INTO #tmp
SELECT *
FROM OPENROWSET (
'SQLOLEDB',
'Server=(local);TRUSTED_CONNECTION=YES;',
'set fmtonly off
EXECUTE dbo.SP1
#P_Source = ''test'''
,#P_Location = ''test'''
)
To help you build up to the final solution you could try having a dummy SP1 that takes two numeric parameters - that'll eliminate some quotes for you to worry about. Once you have that working you can proceed to add string parameters until you get what you want.
For sql linked server use OPENQUERY
https://learn.microsoft.com/en-us/sql/t-sql/functions/openquery-transact-sql
and sp_executesql
DECLARE #P_Source varchar(255) = 'test'
DECLARE #P_Location varchar(255) = 'test'
DECLARE #SQL NVARCHAR(MAX) = '',
#QUERY NVARCHAR(MAX) = '',
#Params NVARCHAR(500) = N'DECLARE #P_Source VARCHAR(255),#P_Location VARCHAR(255); ',
#ParamsValue NVARCHAR(500) = N'SELECT #P_Source = '''''+#P_Source+''''', #P_Location = '''''+#P_Location+''''';'
SET #Query = N'set fmtonly off; EXECUTE dbo.SP1 #P_Source, #P_Location'
SET #SQL = 'SELECT * FROM OPENQUERY([Local],'' sys.sp_executesql ' + #Params + #ParamsValue + #Query +''' )'
INSERT INTO #Tmp
EXEC (#SQL)

run script in multiple Dbs query return error

I am running a query with the sp_MSforeachdb stored procedure. I used three databases which exist in my server instance: ExcelineDev, EXCE_NR1, and EXCE_AKI.
declare #t table (dbname varchar(50),ss varchar(max),sss varchar(max))
DECLARE #command varchar(max)
SELECT #command = 'IF ''?'' IN (''ExcelineDev'',''EXCE_NR1'',''EXCE_AKI'')
BEGIN USE ?
EXEC
(''
select DB_NAME(DB_ID()), category,name from usrpt.report
where name like ''''%leders%''''
'')
END'
print #command
insert into #t
EXEC sp_MSforeachdb #command
select * from #t
I'm getting the following error:
'Msg 911, Level 16, State 1, Line 2 Database 'Migration_Release_1'
does not exist. Make sure that the name is entered correctly.'
I'm confused, because there is no DB called 'Migration_Release_1' in my server instance. Why is SQL searching for this database?

Alter Database Statement in DDL Trigger

I am trying to alter database through a DDL trigger which will fire on creation. However I am getting a below error.
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
declare #dbname as nvarchar(100)
declare #sql as nvarchar(max)
select #dbname =
CAST(eventdata().query(
'/EVENT_INSTANCE/DatabaseName[1]/text()'
) as NVarchar(128))
select #sql = N'SET IMPLICIT_TRANSACTIONS OFF
ALTER DATABASE ' + #dbname+ N' SET COMPATIBILITY_LEVEL = 110
SET IMPLICIT_TRANSACTIONS ON'
exec (#sql)
GO
create database test
Error:
Msg 226, Level 16, State 6, Line 22
ALTER DATABASE statement not allowed within multi-statement transaction.
The statement has been terminated.
I am on SQL Server 2014 on Windows 2012.
If you want a specific compatibility level for each new database created - just set that compatibility level in the model database which is the "template" for all new databases being created ...
No need for a system-level trigger for this ....
I realized the DDL trigger will be on its own transaction and Alter is not allowed if a transaction is already started. So to workaround with this problem I have created SQL Job. and put the Alters in the Job and modified the Trigger to call msdb..start_sql_job.
--Trigger
CREATE TRIGGER ddl_trig_database
ON ALL SERVER
FOR CREATE_DATABASE
AS
exec msdb..sp_start_job 'Initialize Database'
GO
--Job
declare #dbname as nvarchar(100)
declare #sql as nvarchar(max)
select top 1 #dbname = name from sys.databases
where name like 'gtp%' and create_date >= getdate() - .08
order by create_date desc
IF #dbname is not null
begin
select #sql = N'ALTER DATABASE ' + #dbname+ N' SET COMPATIBILITY_LEVEL = 110'
exec sp_executesql #sql
print 'Altered database'
end
print 'completed'

Dynamic Query is not working with cursor in SqlServer 2008 Stored Procedure

I am building a stored procedure in Sql Server 2008. Stored Procedure has two arguments which are the column names of a table. In stored procedure I used dynamic query for fetching data of these two columns with the help of Cursor.
Code:
Create PROCEDURE TestSP
(
#firstAttribute nvarchar(max),
#secondAttribute nvarchar(max)
)
AS
DECLARE #x FLOAT
DECLARE #y INT
DECLARE #query nvarchar(max)
DECLARE #cursor_query nvarchar(max)
DECLARE #result_Cursor as cursor
BEGIN
SET #query = 'Select '+ #firstAttribute+','+#secondAttribute+' from TBL_TEST_DATA_NEW'
SET #cursor_query =' set #cursor = cursor for ' + #query +' open #cursor;'
PRINT 'CURSOR_QUERY'+#cursor_query
exec sys.sp_executesql
#cursor_query
,N'#cursor cursor output'
,#result_Cursor output
FETCH NEXT FROM result_Cursor INTO #x, #y
But when I am executing this SP it is giving me following error
Msg 16916, Level 16, State 1, Procedure TestSP, Line 33
A cursor with the name 'result_Cursor' does not exist.
Execute Command :
Exec TestSP "Column_1","Column_2"
Can someone tell me why I am getting this error
Please Help..
Thanks
The error is saying that Cursor does not exist. You can't start with "set cursor". Also cursor name is without #.
So try using
declare cursorNameHere cursor for SELECT ...
open cursorNameHere
#result_Cursor is a variable, just change your last line to
FETCH NEXT FROM #result_Cursor INTO #x, #y
see example on sql fiddle demo
change
PRINT 'CURSOR_QUERY'+#cursor_query
to
PRINT 'CURSOR_QUERY '+#cursor_query