Exec stored procedure with OpenQuery & parameter - sql

Stored procedure as below. It is using a linked server to Oracle.
ALTER PROCEDURE [dbo].[SVOPS_ZsmartPaymentView]
(#param01 VARCHAR(255))
AS
BEGIN
SELECT *
FROM OPENQUERY(ZSMART_PROD, 'SELECT BANK_SN FROM CC.V_PAYMENT WHERE BANK_SN=''#param01''')
END
If I call the stored procedure with parameters as shown below, the result is empty:
EXEC [dbo].[SVOPS_ZsmartPaymentView] #param01 = 'T131612073600'
But if I run the statement directly like below, there is result.
SELECT *
FROM openquery(ZSMART_PROD, 'SELECT * FROM CC.V_PAYMENT WHERE BANK_SN=''T131612073600''')
Any idea why it returned empty result if executed using the stored procedure?

Try this:
ALTER PROCEDURE [dbo].[SVOPS_ZsmartPaymentView]
(#param01 VARCHAR(255))
AS
BEGIN
SELECT *
FROM OPENQUERY(ZSMART_PROD, 'SELECT BANK_SN FROM CC.V_PAYMENT WHERE BANK_SN=''' + #param01 + '''')
END

I follow the sample from https://support.microsoft.com/en-us/help/314520/how-to-pass-a-variable-to-a-linked-server-query.
And it works.
Pass Basic Values
When the basic Transact-SQL statement is known, but you have to pass in one or more specific values, use code that is similar to the following sample:
DECLARE #TSQL varchar(8000), #VAR char(2) SELECT #VAR = 'CA' SELECT
#TSQL = 'SELECT * FROM OPENQUERY(MyLinkedServer,''SELECT * FROM
pubs.dbo.authors WHERE state = ''''' + #VAR + ''''''')' EXEC (#TSQL)
Thanks.

Related

Does sp_executesql support multiple values in one parameter and return multiple records?

I have created a stored procedure as shown below, but it's returning only one row instead of 3:
CREATE PROCEDURE [dbo].[tempsp]
(#RecycleIds NVARCHAR(MAX) = NULL)
AS
BEGIN
DECLARE #Err INT
DECLARE #WhereClause NVARCHAR(MAX)
DECLARE #SQLText1 NVARCHAR(MAX)
DECLARE #SQLText NVARCHAR(MAX)
SET #SQLText1 = 'SELECT FROM dbo.SKU '
IF #RecycledSkuIds IS NOT NULL
BEGIN
SET #SQLText = 'SELECT FROM dbo.SKU WHERE SKU.SkuId IN (#RecycleIds)'
EXEC sp_executesql #SQLText, N'#RecycleSkuIds nvarchar', #RecycleIds
END
ELSE
BEGIN
EXEC(#SQLText1)
END
SET #Err = ##ERROR
RETURN #Err
END
-------end of stored procedure--------
EXEC tempsp #RecycleIds = '5,6,7'
After running this SQL statement, it only returns one row instead of 3, with the id's of 5, 6, 7.
Can anyone tell me what I am doing wrong?
i wanted to use sp_executesql, so that it can be safe against sql injection with strong type defined.
Use a table type parameter, with a strongly typed column:
CREATE TYPE dbo.IDs AS table (ID int);
GO
CREATE PROCEDURE [dbo].[tempsp] #RecycleIds dbo.IDs READONLY AS
BEGIN
IF EXISTS (SELECT 1 FROM #RecycleIds)
SELECT * --Replace with needed columns
FROM dbo.SKU S
--Using EXISTS in case someone silly puts in the same ID twice.
WHERE EXISTS (SELECT 1
FROM #RecycleIds R
WHERE R.ID = S.SkuID);
ELSE
SELECT * --Replace with needed columns
FROM dbo.SKU S
END;
GO
Then you could execute it like so:
EXEC dbo.tempsp; --All Rows
GO
DECLARE #RecycleIds dbo.IDs;
INSERT INTO #RecycleIds
VALUES(1),(40),(182);
EXEC dbo.tempsp #RecycleIds;
I was trying to retrive the rows whose id matches within the IN clause.
SET #INClauseIds='''' + replace(#Ids, ',', ''',''') + ''''
Above statement would convert the ID's ='1,2,3' to '1','2','3' which i can directly place in the IN clause.
SET #SQLText1 ='EXEC(''SELECT Name,SEOFriendlyName FROM SKU Where Id IN ( ''+ #Ids+'' ) )'
EXEC sp_executesql #SQLText1 ,N'#INClauseIds nvarchar(max)',#Ids=#INClauseIds
If you want to avoid the usage of Temp Table which would add extra caliculation time. you can you the above strategy to retrive n number of records. Safe with strongly coupled with sp_executesql and without any sql injection.
You cannot use IN. Or, more accurately, you have a string and you are confusing it with a list. One method is to instead use LIKE:
SET #SQLText = '
SELECT *
FROM dbo.SKU
WHERE CONCAT('','', #RecycleIds, '','') LIKE CONCAT(''%,'', SKU.SkuId, '',%'')
';

Sybase SQL - Stored Procedure

I’m trying to create a very simple stored procedure which would do the following:
EXEC sp_help N’some.table’
SELECT TOP 1000 * FROM some.table
So far I have the following
CREATE PROCEDURE info_qry(#tbl)
BEGIN
DECLARE #tbl varchar(100)
EXEC sp_help N’#tbl’
SELECT TOP 1000 * FROM #tbl
END
I can’t figure it out how to pass the #tbl variable after the N’’ part so it is taken as a variable and not as a constant. How to do that?
Any help is appreciated.
Apologies about formatting I’m on mobile.
You can use dynamic SQL:
declare #sql nvarchar(max);
set #sql = 'sp_help ''' + #tbl + '''';
exec(#sql);

OPENQUERY(SERVERNAME, STOREDPROCEDURE) Syntax error

This is my code
DECLARE #stringvariable nvarchar(200) = 'Hello';
DECLARE #sql nvarchar(2000) = SELECT * INTO ##global FROM OPENQUERY(DB1, ''EXEC GETCASE ''' + #stringvariable + ''''')'
Printing #sql returns a correctly formatted query, however SQL Server doesn't like #stringvariable and returns an error
Msg 102, Level 15, State 1, Line 11
Incorrect syntax near 'Hello'.
Here is what the outputted query looks like
SELECT * INTO ##global FROM OPENQUERY(DB1, 'EXEC GETCASE 'Hello'')
How can I avoid this error? It seems like because my stored procedure takes a string parameter, it's throwing off the query. I've read that OPENQUERY does not support variables, but I've parameter the variable so it should work?
Appreciate your help!
The stored procedure exists in a database and a schema. You need to supply those. Supposing database db_name and schema schema_name:
DECLARE #stringvariable nvarchar(200) = 'Hello';
SET #stringvariable=REPLACE(#stringvariable,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #sql nvarchar(2000) = 'SELECT * INTO ##global FROM OPENQUERY(DB1, ''SET FMTONLY OFF;EXEC db_name.schema_name.GETCASE ''''' + #stringvariable + ''''''')';
I've also made sure single quotes are properly escaped in the #stringvariable.
It's also likely you need to start the query with SET FMTONLY OFF; so I've added that.
Update: To test this I created following simple procedure on a linked server local_server in database TEST_TT
CREATE PROCEDURE [dbo].[tst]
#i VARCHAR(128)
AS
SELECT #i AS field;
I then ran the following:
DECLARE #var VARCHAR(128)='TT.';
SET #var=REPLACE(#var,'''',''''''''''); -- doubly doubled single quotes for the dynamic statement
DECLARE #stmt VARCHAR(4000)='SELECT * INTO ##tt FROM OPENQUERY(local_server,''SET FMTONLY OFF;EXEC TEST_TT.dbo.tst '''''+#var+''''''');';
EXEC (#stmt);
SELECT * FROM ##tt;
DROP TABLE ##tt;
And I received the results. I count 7 (!!) single quotes at the end of the query... yuck! Updated original part with the same number of quotes.

Merging two dynamic SQL statements into one

So I made a procedure that makes a dynamic view using dynamic SQL, but I used two sql executions: One for the if clause and one for the else, it should be possible to put it all under one SQL string or am i wrong? Because I tried it and get an error over and over again. Im not the best in writing dynamic sql, so it is probably my mistake or cant it be done and im losing my time on trying to do this?
create procedure test_view
(#table_name varchar(30))
as
BEGIN
declare# sqlQuery varchar(100)
if exists(select 1 from sp_iqview('v_anon_' + #table_name) where view_name = 'v_anon_' + #table_name)
begin
set# sqlQuery = ('drop view ' + 'v_anon_' + #table_name)
EXECUTE(#sqlQuery)
end
else
begin
set# sqlQuery = ('CREATE VIEW ' + 'v_anon_' + #table_name + ' AS SeLECT * FROM ' + #table_name)
EXECUTE(#sqlQuery)
select# sqlQuery
end
END
try this query.... Here else statement is not required.... if the object exists, it will drop in the first step itself. If not, it create new one...
create procedure test_view
(#table_name varchar(30))
as
BEGIN
declare #DropQuery varchar(100)
declare #CreateQuery varchar(100)
IF EXISTS(select 1 from sp_iqview('v_anon_' + #table_name) where view_name = 'v_anon_' + #table_name)
BEGIN
SET #DropQuery= 'drop view v_anon_' + #table_name
EXEC sp_executesql #DropQuery
END
SET #CreateQuery = 'CREATE VIEW v_anon_' + #table_name + ' AS SeLECT * FROM ' + #table_name
EXEC sp_executesql #CreateQuery
SELECT #CreateQuery
END
You would need a go between the two statements, but dynamic SQL doesn't support the GO keyword as it's not valid T-SQL. You would need to execution them separately...
However you could add go and then go with a solution proposed here I suppose...
Execute Dynamic Query with go in sql

stored procedure input parameter

i am creating a stored procedure in sql server 2008 such as this
-- the code
create procedure proce
#database varchar(50)
as
begin
select * from [#database].[dbo].[sometable]
end
the procedure is compiled
but when i execute the procedure using
-- here i execute it
execute proce 'somedatabase'
it throws an error
-- me gets error :(
Invalid object name '#database.dbo.sometable'
where am i going wrong???????
You cannot directly parameterized the tableName. The only way you can do that is to make a dynamic SQL Statement.
eg,
CREATE PROCEDURE proce #database VARCHAR(50)
AS
BEGIN
DECLARE #SQLQuery AS NVARCHAR(500)
SET #SQLQuery = 'SELECT * FROM [' + #database + '].[dbo].[sometable]'
EXECUTE(#SQLQuery)
END
GO
Building Dynamic SQL In a Stored Procedure
You can go with this:
DECLARE #string AS NVARCHAR(500)
SET #string = 'select * from [' + #database + '].[dbo].[sometable]'
EXEC (#string)
More more info refer: Dynamic SQL
I don't believe variables are allowed in that context, use the following which I've just confirmed works with your procedure:
exec('select * from [' + #database + '].[dbo].[sometable]')