TSQL update openquery with params - tsql

I have successfully dont a query using something like the following but I can't do an update with 'variables' I can without them. Is this possible? This complains that
'Incorrect syntax near ' set stuf_rec.stat = "A"
DECLARE #stuf_no varchar(6)
set #stuf_no = 267
DECLARE #sql varchar (2000)
set #sql =
'UPDATE OPENQUERY(train,''select stat from stuf_rec
where stuf_no = '+ #stuf_no + ''')'' set stuf_rec.stat = ' + '"A"' + '
where stuf_rec.stuf_no = ' + #stuf_no + ''';'
Thanks..

Does this work for ya? Or does the value have to have the double quotes?
DECLARE #stuf_no varchar(6)
set #stuf_no = '267'
DECLARE #sql varchar (2000)
set #sql =
'UPDATE OPENQUERY(train,''select stat from stuf_rec
where stuf_no = '+ #stuf_no + ''') set stuf_rec.stat = ''A''
where stuf_rec.stuf_no = ' + #stuf_no + ';'
The result of #sql looks like the following:
UPDATE OPENQUERY(train,'select stat from stuf_rec
where stuf_no = 267')
set stuf_rec.stat = 'A'
where stuf_rec.stuf_no = 267;

Related

Getting Error With GROUP BY when Converting Query to Dynamic SQL

I'm trying to convert the following query to dynamic SQL to allow for variations:
UPDATE T
SET SumCount = J.SUM
FROM #temp T
JOIN (SELECT Count_99221 + COUNT_99222 + Count_99223 [SUM], t2.userID
FROM #temp t2
GROUP BY t2.userID, Count_99221 + COUNT_99222 + Count_99223
) J ON T.userID = J.UserID
This is what I have for the Dynamic SQL:
DECLARE #sql3 nvarchar(2000) =
'UPDATE T ' +
'SET SumCount = J.SumOfColumns ' +
'FROM #temp T ' +
'JOIN (SELECT ' + #columnSumString + ' [SumOfColumns], t2.userID ' +
'FROM #temp t2 ' +
'GROUP BY t2.userID, ' + #columnSumString +
' ) J ON T.userID = J.UserID'
EXEC sp_executesql #sql3
I am receiving the following error only when I run the query as Dynamic SQL:
Each GROUP BY expression must contain at least one column that is not
an outer reference.
Can somebody help explain why this is happening? I am new to Dynamic SQL so I'm not privy to any limitations for running queries this way.
Thank you in advance.
EDIT:
The variable #columnString is a string made by concatenating several other column names, created in the following way:
DECLARE #Cursor Cursor
DECLARE #code varchar(20)
DECLARE #ID INT
SET #cptCursor = CURSOR FOR
SELECT * FROM dbo.Split(#UserInput,CHAR(44))
OPEN #cptCursor
FETCH NEXT FROM #cptCursor INTO #ID, #code
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #colName varchar(50) = 'Count_' + cast(#code as varchar(10))
DECLARE #sql nvarchar(50) = 'ALTER TABLE #temp ADD ' + #colName + ' int'
EXEC sp_executesql #sql
--Code that adds values to each column that is created.....
SET #columnSumString = #colName + ' + ' + #columnSumString
--SET #columnSumString = #code + ' + ' + #columnSumString
FETCH NEXT FROM #cptCursor INTO #ID, #code
END
CLOSE #Cursor
DEALLOCATE #Cursor
SET #columnSumString = SUBSTRING(#columnSumString,1,LEN(#columnSumString)-2)
SELECT #columnSumString
The user input is a comma separated string. "Count_99221 + COUNT_99222 + Count_99223" is just one example of columns created from the user input "99221, 99222, 99223".
I also realized I was concatenating the #code variable into #columnSumString instead of #colName. Now when I run the query I don't get the error (even though I don't understand how the above error message relates to that mistake) but every value of SumCount is NULL.
IMHO you must re-write your query as follow:
UPDATE #temp
SET SumCount =
(SELECT Count_99221 + COUNT_99222 + Count_99223
FROM #temp t2
WHERE t2.userID = #temp.userID)
So the dynamic SQL will become:
DECLARE #columnString varchar(200)
SET #columnString = Count_99221 + COUNT_99222 + Count_99223
DECLARE #sql3 nvarchar(2000) =
N'UPDATE #temp ' +
'SET SumCount = (SELECT ' + #columnString +
' FROM #temp t2 WHERE t2.userID = #temp.userID)'
EXEC sp_executesql #sql3

SQL - insert into QUOTENAME(#DatabaseName)

DECLARE #DatabaseName varchar(30), #Article varchar(16), #PartnerID int
set #DatabaseName = 'DEMO'
set #Article = 'Article1'
set #PartnerID = 1
INSERT INTO QUOTENAME(#DatabaseName) + '.dbo.move(Article, Partner, Note)'
select #Article, #PartnerID, 'Note'
I have this and error is:
Msg 102, Level 15, State 1, Line 7
Incorrect syntax near '+'.
I try:
DECLARE #SQL nvarchar(max)
DECLARE #DatabaseName varchar(30), #Article varchar(16), #PartnerID int
set #DatabaseName = 'Demo'
set #Article = 'Article1'
set #PartnerID = 1
set #SQL = N'INSERT INTO '+ QUOTENAME(#DatabaseName) + N'.dbo.move(Article, Partner, Note)'
+ N'select ' + #Article + N', ' + #PartnerID + N', '''Note''' '
exec #SQL
But I get this error:
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near 'Note'.
If you are going to use dynamic SQL (which should be avoided if you have alternatives), it's still a good idea to use sp_executesql and parameters, and using REPLACE to construct statements rather than concatenation saves a lot of headaches debugging the proper escaping. In your example:
SET #SQL = REPLACE(
'INSERT INTO $database.dbo.move(Article, Partner, Note)
VALUES (#Article, #Partner, ''Note'')',
'$database', QUOTENAME(#DatabaseName)
);
PRINT #SQL; -- check what we've produced
EXECUTE sp_executesql
#stmt = #sql,
#params = N'#Article VARCHAR(16), #Partner INT',
#Article = #Article, #Partner = #PartnerID
;

Inserting DateTime into datetime field TSQL

I'm trying to call a stored procedure in SQL Server 2012 Express from a C# program, to insert a DateTime data type into a column (which is also datetime).
For some reason, I keep getting errors about "Conversation failed when converting date and/or time from character string."
I've checked the culture settings in my SQL server, which is set to us_english, but the datetime format is the ISO standard.
Here's the code from the stored procedure. The values are exactly how they're passed by the C# app.
USE testdb;
DECLARE #Name NVARCHAR(50) = 'Somename',
#Location NVARCHAR(50) = 'somelocation',
#Date DateTime = '2013-10-11 11:00:05.000'
BEGIN
SET NOCOUNT ON;
SELECT #Name, #Location, #Date
if exists (select name from ComputerHistory where name = #Name)
begin
DECLARE #Query1 NVARCHAR(MAX)
if #Location <> 'disconnected'
begin
set #Query1 = '
update ComputerHistory
set ' + #Location + ' = 1 + ISNULL((select MAX(' + #Location + ') from ComputerHistory where name = ''' + #Name + '''),0),
lastdateonline = ''' + #Date + '''
where name = ''' + #Name + '''
'
--EXEC sp_executesql #Query1
end
else
begin
set #Query1 = '
update ComputerHistory
set ' + #Location + ' = 1 + ISNULL((select MAX(' + #Location + ') from ComputerHistory where name = ''' + #Name + '''),0)
where name = ''' + #Name + '''
'
EXEC sp_executesql #Query1
end
end
else
begin
DECLARE #Query2 NVARCHAR(150)
set #Query2 = 'insert into ComputerHistory(name, ' + #Location + ') VALUES(''' + #Name + ''', ''1'')'
EXEC sp_executesql #Query2
end
END
Try cast(#Date as nvarchar(50))
set #Query1 = '
update ComputerHistory
set ' + #Location + ' = 1 + ISNULL((select MAX(' + #Location + ') from ComputerHistory where name = ''' + #Name + '''),0),
lastdateonline = ''' + cast(#Date as nvarchar(50)) + '''
where name = ''' + #Name + '''
'

Dynamic Query w/ Quotes issue

I'm trying to write a dynamic query that produces the same results as the following, but replaces the fixed tablename with a variable.
SELECT *
WHERE tableName = 'Table2A'
works fine but
DECLARE #tablename AS NVARCHAR(100)
SET #tablename = N'Table2A'
DECLARE #execquery AS NVARCHAR(MAX)
SET #execquery = N'
SELECT *
WHERE tableName = ''' + QUOTENAME(#tablename) + N''''
EXECUTE sp_executesql #execquery
returns no records. What am I doing wrong?
Aside from the fact that your SQL statement is invalid, QUOTENAME() simply places brackets "[]" around the supplied variable. Replace the EXECUTE statement with a PRINT statement, and you'll get the following results:
DECLARE #tablename AS NVARCHAR(100)
SET #tablename = N'Table2A'
DECLARE #execquery AS NVARCHAR(MAX)
SET #execquery = N'
SELECT *
WHERE tableName = ''' + QUOTENAME(#tablename) + N''''
PRINT #execquery
--EXECUTE sp_executesql #execquery
RESULTS:
SELECT *
WHERE tableName = '[Table2A]'

Update Sql db with a NULL value passed from Parameter

I need to store a value with Null which is passed from a parameterized query using VB.net into SSEE 2008 R2.
The value maybe either 'Null' or a blank string "". How can I test for this and properly UPDATE the field in my Stored Procedure?
EDIT: Added declarations.
#ID int,
#currTable varchar(150),
#prev_LangString nvarchar(max),
#brief_Descrip nvarchar(max)
BEGIN
IF #brief_Descrip IS NULL OR #brief_Descrip = 'Null'
SET #brief_Descrip = 'Null';
END
BEGIN
SET #sql = 'UPDATE ' + #currTable + ' SET [date_Changed] = ''' + convert(varchar(20), #submitDate1) + ''', [prev_LangString] = ''' + #prev_LangString + ''', [brief_Descrip] = ''' + #brief_Descrip + '''
WHERE (ID = ' + CAST(#ID as nvarchar(10)) + '); '
EXECUTE(#sql);
END
Thanks for any help on this.
The problem is that you are converting #brief_Descript to a string. This will also fix your injection vulnerability.
BEGIN
IF #brief_Descrip = 'Null'
SET #brief_Descrip = NULL;
END
UPDATE TABLE table_name
SET
date_Changed = convert(varchar(20), #submitDate1),
prev_LangString = #prev_LangString,
brief_Descrip = #brief_Descrip,
WHERE
ID = CAST(#ID as nvarchar(10))
EDIT
The best way to fix this is to convert the string null to DBNull in vb.net, and use a parameterized query with an update statement.
You should not convert the date to a string. Change the column type to a date time.
Another option would be to use a parameterized query. It would even make your problem go away. Like this:
DECLARE #sql NVARCHAR(4000), #params NVARCHAR(4000)
SET #sql = 'UPDATE ' + #currTable + ' SET date_changed = #p0, prev_langstring = #p1, brief_descrip = #p2 WHERE id = #p3'
SET #params = '#p0 VARCHAR(20), #p1 VARCHAR(???), #p2 VARCHAR(???), #p3 NVARCHAR(10)'
DECLARE #sd VARCHAR(20), #sid NVARCHAR(10)
SET #sd = CONVERT(VARCHAR(20), #submiteDate1)
SET #sid = CAST(#ID AS NVARCHAR(10))
EXEC sp_executesql #sql, #params, #p0 = #sd, #p1 = #prev_langstring, #p2 = #brief_descrip, #p3 = #sid
I don't know the datatype of #prev_langstring and of #brief_descrip, hence the VARCHAR(???) you see above; replace it by the real datatype.
You can read about sp_executesql here.