Passing xml to stored procedure on linked server - sql-server

I've tried something like this:
declare #xml as xml
SET #xml =
(
SELECT DISTINCT
123 AS IdUser
FROM
(
SELECT
1 AS a
) AS ic FOR
XML AUTO
);
exec [linked_server_name].[mydb].[dbo].[stored_procedure] #xml=#xml
Got Msg 9514, Level 16, State 1, Line 5
Tried converting input parameter to varchar(max) and converting it back inside linked server
Still got Msg 9514, Level 16, State 1, Line 5.
Tried executing via openquery - still got Msg 9514, Level 16, State 1, Line 5

Overall, you were on the right path to a solution. If your database is SQL Server, passing XML via linked servers is not supported. Casting it to NVARCHAR(MAX) is a recommended workaround. Along the following:
SQL
DECLARE #xml AS XML =
CAST('' AS XML).query('
element ic {
attribute IdUser {"123"}
}
');
DECLARE #par NVARCHAR(MAX) = CAST(#xml AS NVARCHAR(MAX));
exec [linked_server_name].[mydb].[dbo].[stored_procedure] #xml=#par;

Related

Update the same table for multiple databases within the same server in SQL Server 2014

I want to be able to update the column of the same table in different databases at the same time within the same server, but to start before starting to fill it through a temporary table I wanted to test that it came out with a database, it should be clarified that the structure of the table it is the same in all the databases and that the script would be executed going through the temporary table row by row, so I needed to test it with at least one and then replaced the declared variables.
However, I get the following error, I have not found a solution or another way to do it, I do it to avoid doing it manually 1x1 on each database and it is done automatically:
Msg 4104, Level 16, State 1, Line 16
The multi-part identifier "test#gmail.com" could not be bound.
This is the code I tried:
use master
go
DECLARE #SQL NVARCHAR(MAX) = '';
DECLARE #NAMEBD NVARCHAR(MAX) = 'Here_goes_the_name_of_the_DB';
DECLARE #MAIL NVARCHAR(MAX) = 'test#gmail.com';
SELECT #SQL = #SQL +
'USE ' + QUOTENAME(NAME) + ';
UPDATE dbo.companyconfig
SET originMail ='+#MAIL+';'
FROM sys.databases
WHERE name = #NAMEBD;
EXEC sp_executesql #SQL;
I was hoping it would update but I only get the error shown.
I also tried using sp_MSforeachdb and it gives me the same result.
I already managed to solve it, I did it this way:
DECLARE #SQL NVARCHAR(MAX) = '';
DECLARE #NAMEBD NVARCHAR(MAX) = 'Here_goes_the_name_of_the_DB';
DECLARE #MAIL NVARCHAR(MAX) = 'test#gmail.com';
SELECT #SQL = #SQL + '
UPDATE compconfig
SET originMail ='''+#MAIL+'''
FROM '+QUOTENAME(#NAMEBD)+'.dbo.companyconfig As compconfig;'
FROM sys.databases
WHERE name = #NAMEBD;
EXEC sp_executesql #SQL;
It was necessary to set the field having to double the quotes.

Get database name dynamically

I am trying to get the database name dynamically but, showing some errors.
What I have tried:
Declare #dbname varchar(40) = (select name from sys.databases where name like '%worksdw2019')
select db_name() as [Database], *
from #dbname.dbo.DimCustomer with (readuncommitted)
How end result should look like
select db_name() as [Database], *
from AdventureWorksdw2019.dbo.dimcustomer
These are the errors I am getting:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '.'.
Msg 319, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
You can't parameterize database names, so you'll need dynamic SQL.
DECLARE #context nvarchar(1000);
SELECT #context = QUOTENAME(name) + N'.sys.sp_executesql'
from sys.databases
where name like N'%worksdw2019';
-- what if there is more than one?
DECLARE #sql nvarchar(max) = N'select db_name() as [Database], *
from dbo.DimCustomer;';
EXECUTE #context #sql;
Uh, with (readuncommitted) -> why? sqlblog.org/nolock
You have invalid SQL written.
You cannot write use a variable like that in SQL Server. If the database name is going to be variable as seen in your example, you will need to execute dynamic SQL using the EXEC command such as this example below:
Declare #dbname varchar(40) = (select name from sys.databases where name like '%HelloWorld')
EXEC('select db_name() as [Database], * from ' + #dbname + '.dbo.DimCustomer with (readuncommitted);')
-- you may additionally need to escape your database name
-- if you are using special characters in your name

Insert Temp Table Failing with Parsing Error on Exec

I want to insert the result set coming from a query into a temporary table in Azure SQL Data Warehouse. I used the below statements but I am getting a parse error:
DECLARE #SQL2 NVARCHAR(1000)
CREATE taBLE #TempTable (L NVARCHAR(100))
SET #SQL2 = 'SELECT Col1 FROM Table1'
INSERT INTO #TempTable (L) EXEC SQL2***
Msg 103010, Level 16, State 1, Line 44
Parse error at line: 5, column: 28: Incorrect syntax near 'EXEC'.
I even tried Declare #T TABLE (ID iNT) still getting a parse error.
I got answer minutes after uploading the question
Azure SQL Data Warehouse does not support INSERT ... EXEC
For explanation and an alternative approach: https://learn.microsoft.com/en-gb/azure/sql-data-warehouse/sql-data-warehouse-develop-stored-procedures#insertexecute

How to get list of databases from a linked server

I have to look up for results on linked servers' databases. First I should know what dbs are available on a linked server. I tried to use the below query but gives an error.
What would be the proper way?
...
set #base_query_db_list =
'
select
''#server'',
name,
database_id,
create_date
from #server.sys.databases
'
set #server = '[linked_server_name]'
set #query_db_list = replace(#base_query_db_list, '#server', #server)
insert into #db_list
EXECUTE sp_executesql #query_db_list
...
Error:
Msg 208, Level 16, State 1, Line 2
Invalid object name '[linked_server_name].sys.databases'.

SQL variable for Database Name

I am trying to pass a database name in as a parameter and execute some dynamic SQL. As a test I created this:
declare #HRMSDatabase_1 nvarchar(50) = N'FirstDatabase',
#Example_1 nvarchar(max) =
'select #HRMSDatabase'
execute sp_executesql #Example_1, N'#HRMSDatabase nvarchar(50)', #HRMSDatabase_1
which returns FirstDatabase as I expected.
When I try this:
declare #HRMSDatabase_2 nvarchar(50) = N'FirstDatabase',
#Example_2 nvarchar(max) =
'select
''Test''
from
#HRMSDatabase.dbo.hrpersnl hp'
execute sp_executesql #Example_2, N'#HRMSDatabase nvarchar(50)', #HRMSDatabase_2
I get an error message:
Msg 102, Level 15, State 1, Line 29
Incorrect syntax near '.'.
Is what I am trying to do possible? I cannot simply use a USE FirstDatabase as I have a few databases I have to query in the same dynamic SQL using inner joins.
Also, I cannot use SQLCMD as this script gets executed from a GUI.
Basically, I don't believe you can parameterize the database name in the table specifier. Instead try this,
DECLARE #HRMSDatabase NVARCHAR(50) = N'FirstDatabase';
DECLARE #Example3 NVARCHAR(MAX) ='SELECT
''Test''
FROM
' + QUOTENAME(#HRMSDatabase) + '.[dbo].[hrpersnl] hp';
EXEC sp_executesql #Example3;
As you'll note, it's important that the #HRMSDatabase is not recieved from user input as this would be susceptible to injection attacks.

Resources