SQL server linked server update - sql

Currently working on a script which can update a number of different tables across linked servers. I use 08/12 SQL server management studio.
I am having an issue where I have tried to set up the linked server string as a variable, so I can set this at the beginning and reference when needed through the script. I have been working on the assumption I can declare this as a local variable, as I have for other parts of my script that are updating the local table/server, but when running the script, I receive an incorrect syntax error for the section of code my linked server string variable is located.
My code is structured as:
declare #string varchar(max)
set #string = '[server,instance].[database].dbo.table1'
update #string
set field = updatevariable
where record = identifier
Is it possible to use a linked server as a variable?

You can dynamically construct SQL Update string, and then pass it to exec. Example:
declare
#srv nvarchar(max) = N'[server].[db].[dbo].[table]',
#id int = 100,
#value nvarchar(max) = N'some value',
#sql nvarchar(max)
set #sql = N'update ' + #srv
+ ' set field = ''' + #value + ''' '
+ ' where record = ' + cast(#id as nvarchar)
exec(#sql)

Related

Use dynamic column name in where clause without executing a variable

I use SQL Server and have the following query:
declare #variable nvarchar(max)
set #variable = 'Fixed_Assets'
declare #sql nvarchar(max)
set #sql = 'Select ' + #variable + ' from table where ' + #variable + '= 1 '
But how could I still use #variable as a value and not a column name?
I want to add a column (Name) and then with the constant value of Fixed Assets
You can't directly insert a variable as a column name into a command, but you can create a command as a nvarchar, concat another variable into it (in your case the column name), then use Exec() to run it.
DECLARE #variable varchar(10)
SET #variable = 'YourColumn'
DECLARE #sqlCommandText nvarchar(1000);
SET #sqlCommandText = N'select * from table where ' + #variable + ' = ''1'''
Exec (#sqlCommandText)
Don't forget if you have a single quote inside a string in sql you need to escape them by doubling them up.

How to pass column names in a SQL query as parameters using report builder 3.0

I am using "Microsoft SQL Server Report Builder 3.0" on "SQL Server Reporting Services 2012".
From a main report main.rdl I am calling a drillthrough report detail.rdl
The main.rdl report has a table and each text box of this table is clickable and drillthrough action. When user clicks on any text box the detail.rdl report is called. One parameter that is passed to detail.rdl report is used as a column name in the SQL. This SQL fetches data needed for detail.rdl report
When I run the SQL query for detail.rdl report that is built using parameters, it is not showing any error but doesn't fetch any data either. I think what is happening is that as the parameter has data type Text, it's replaced in SQL with quotes which might be causing it not to fetch any data.
When I run the same SQL directly on DB after replacing the column name with parameter value (without quotes) it does fetch data.
Is there any specific way to pass parameters that will be used as column names that I am missing here?
SQL that I am trying from report builder:
SELECT
table_name.column1
,table_name.column21
,table_name.column15
,table_name.column6
,table_name.column9
,table_name.column2
,table_name.column19
,#column --the value in this variable is an existing column name from table table_name
FROM
table_name
WHERE
table_name.column1 LIKE #company
AND table_name.column21 LIKE #platform
AND (#column is null OR #column = '' OR #column = 'N/A' OR #column = 'Unknown');--I want to use same variable here as well
UPDATE:
I was able to get the SQL working by adding
DECLARE #company varchar(10)
SET #company = ''company_name''
DECLARE #platform varchar(10)
SET #platform = ''platform_name''
after the line
SET #SQL =
'
Unfortunately "Microsoft SQL Server Report Builder 3.0" is not able to execute this SQL as it asks for value of variable #SQL even though it's value is defined. I did try Declaring and setting the value of #SQL in same line as:
DECLARE #SQL varchar(5000) = 'DECLARE #company varchar(10)
But report builder still asks for value of #SQL and report doesn't run :-(
It's hard to tell what the problem is without seeing your code but you can't just swap a string in the SQL like (I think) you are trying to do.
To test your SQL just do something simple in Management Studio like
DECLARE #MyParm varchar(256) = 'myColumnName'
SELECT *, #MyParm FROM myTable
This will return all columns from MyTable, plus a string value of 'myColumnName' as the final column.
If this is what you are trying to do then you'll probably need to change your SQL to use dynamic SQL, something like this.
DECLARE #MyParm varchar(256) = 'myCOlumnName'
DECLARE #SQL varchar(max)
SET #SQL = 'SELECT *, ' + #MyParm + ' FROM myTable'
EXEC (#SQL)
If I've got this completely wrong, please post some sample code so we can see what you are attempting.
EDIT: here is a specific answer based on your sample code
DECLARE #Column sysname = 'Column999'
DECLARE #SQL varchar(max)
SET #SQL =
'SELECT
table_name.column1 ,table_name.column21 ,table_name.column15 ,table_name.column6
,table_name.column9 ,table_name.column2 ,table_name.column19
,' + #column +
' FROM table_name
WHERE table_name.company LIKE #company
AND table_name.platform LIKE #platform
AND (' + #column + ' is null OR ' + #column + ' = '''' OR ' + #column + ' = ''N/A'' OR ' + #column + ' = ''Unknown'')'
-- uncomment below to check SQL statement is correct
--print #sql
-- exec the SQL statement
exec (#sql)
As it stands, this will execute the following sql
SELECT
table_name.column1 ,table_name.column21 ,table_name.column15 ,table_name.column6
,table_name.column9 ,table_name.column2 ,table_name.column19
,Column999 FROM table_name
WHERE table_name.company LIKE #company
AND table_name.platform LIKE #platform
AND (Column999 is null OR Column999 = '' OR Column999 = 'N/A' OR Column999 = 'Unknown')

Stumped on SQL Server 2008 R2 Conversion failed when converting date and/or time from character string

I am using SQL Server 2008 R2 with Classic ASP on Windows Server 2008 R2/IIS. I know classic ASP is pretty long in the tooth but it works fine with the stored procedures I am using. I have a stored procedure that does a simple update on a smalldatetime column, but I am now trying to make this procedure a dynamic one using a variable table name.
The standard procedure that works fine is:
CREATE PROCEDURE [dbo].[spendemerg]
(
#rfid int
)
AS
BEGIN
SET NOCOUNT ON;
Update EmergencyContent
Set content_expiry = DATEADD(minute, -10, GETDATE())
Where content_id = #rfid
END
I am passing the variable parameter #rfid using ADO and it works fine. When I tried to change the procedure to use dynamic SQL to pass the table name as a variable, that's when I got into trouble.
This is the dynamic procedure:
ALTER PROCEDURE [dbo].[spendBroadcast]
#rfid int,
#strTable varchar(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL nvarchar(MAX);
SET #SQL = 'UPDATE ' + #strTable +
' SET content_expiry = '''+ CONVERT(datetime,(DATEADD(minute, -10, GETDATE())), 121) +
''' WHERE content_id = '+ #rfid
EXEC(#SQL)
END
The code runs ok in a query editor using the SQL management studio, but when executed via IIS/CLassic ASP, it fails with the error:
Conversion failed when converting date and/or time from character string
when executing the stored procedure.
This is the ASP code:
Set objCm = Server.CreateObject("ADODB.Command")
Set objRe = Server.CreateObject("ADODB.Recordset")
objCm.ActiveConnection = objConn
objCm.CommandText = "spendBroadcast"
objCm.CommandType = adCmdStoredProc
Set objParam = objCm.CreateParameter("rfid",adInteger,adParamInput,4, strID)
objCm.Parameters.Append objParam
Set objParam = objCm.CreateParameter("strTable",adVarChar,adParamInput,100, strTableName)
objCm.Parameters.Append objParam
Set objRe = objCm.Execute
Any thoughts and help would be greatly appreciated... thanks!
Since you are building a dynamic SQL string then everything should be the same datatype (notice the 2 added conversions below):
SET #SQL = 'UPDATE ' + #strTable + ' SET content_expiry = '''
+ cast(CONVERT(datetime,(DATEADD(minute,-10,GETDATE())),121) as nvarchar(100))
+''' WHERE content_id = ' + cast(#rfid as nvarchar(100))

"EXECUTE" function within trigger not functioning in TSQL on SERVER

This is my code I am attempting to run inside a trigger. In a trigger it fails because of the EXEC line. I know this because when I take it out, the code at least finishes execution. If I leave it in it, it doesn't even bother finishing. I know this because if I take out the exec line, it will write the sql line to the error table.
I have to use an EXEC command here to write to the remote server. I can't use a nvarchar variable to define the server. Insert expects an explicit table or a table variable. I need to be able to write to this remote server AND I don't know the name of it until runtime, so I can't be explicit. How do I use an EXEC inside a trigger or is there another way to skin this cat?
DECLARE #acctNum int
DECLARE #tickets nvarchar(MAX)
DECLARE #server nvarchar(64)
DECLARE #sql nvarchar(MAX)
if EXISTS (SELECT * FROM dbo.queueNames WHERE queueName = 'queue1')
BEGIN
SELECT #server = queueServer FROM dbo.queueNames WHERE queueName = 'queue1'
SET #server = #server + '.[AMEETING].dbo.tblMembers'
SELECT TOP 1 #acctNum = AccountNum, #tickets = Tickets FROM dbo.queue1 ORDER BY AccountNum
SET #sql = 'UPDATE ' + #server + ' SET Present = ''1'', Tickets = ''' + #tickets + ''' WHERE AccountNum = ' + convert(nvarchar(64),#acctNum)
INSERT INTO dbo.errors values (#sql)
EXEC (#sql)
DELETE FROM dbo.queue1 WHERE AccountNum = #acctNum
END
I am giving up on this and have gone with using text files on the local server and running processes in the background there to queue the sql statements.

SQL Server 2008 R2 error in generating the script

I am trying to generated the script of a database on SQL Server 2008 R2
I got this error
Microsoft.SqlServer.Management.Smo.PropertyCannotBeRetrievedException: Property TextHeader is not available for StoredProcedure '[dbo].[p_SYS_GetQDNPassword]'. This property may not exist for this object, or may not be retrievable due to insufficient access rights. The text is encrypted. at Microsoft.SqlServer.Management.SqlScriptPublish.GeneratePublishPage.worker_DoWork(Object sender, DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e) at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
Could you help please?
I don't know what other information you need, but whatever you need, tell me please to give you.
Using the sp_helptext dbo.p_SYS_GetQDNPassword should give you the result:
"The text for object 'YourProcedureName' is encrypted."
This means that stored procedure is created using WITH ENCRYPTION, and SQL Server internally stores the text with the definition of the object in an obfuscated format
The actual definition of an object is stored in system table sys.sysobjvalues which is not directly accessible. By connecting to SQL Server using the Dedicated Administrator Connection (DAC) you can select the imageval column in which the information is stored
Click on Database Engine Query button:
The Connect To Database Engine dialog will pop out. Type the "admin:" prefix before the server name and you'll be connected to DAC
You can find useful info here in this article
http://www.mssqltips.com/sqlservertip/2964/encrypting-and-decrypting-sql-server-stored-procedures-views-and-userdefined-functions/
When you're connected to DAC run the following script from the article:
SET NOCOUNT ON
GO
ALTER PROCEDURE dbo.TestDecryption WITH ENCRYPTION AS
BEGIN
PRINT 'This text is going to be decrypted'
END
GO
DECLARE #encrypted NVARCHAR(MAX)
SET #encrypted = (
SELECT imageval
FROM sys.sysobjvalues
WHERE OBJECT_NAME(objid) = 'TestDecryption' )
DECLARE #encryptedLength INT
SET #encryptedLength = DATALENGTH(#encrypted) / 2
DECLARE #procedureHeader NVARCHAR(MAX)
SET #procedureHeader = N'ALTER PROCEDURE dbo.TestDecryption WITH ENCRYPTION AS '
SET #procedureHeader = #procedureHeader + REPLICATE(N'-',(#encryptedLength
- LEN(#procedureHeader)))
EXEC sp_executesql #procedureHeader
DECLARE #blankEncrypted NVARCHAR(MAX)
SET #blankEncrypted = (
SELECT imageval
FROM sys.sysobjvalues
WHERE OBJECT_NAME(objid) = 'TestDecryption' )
SET #procedureHeader = N'CREATE PROCEDURE dbo.TestDecryption WITH ENCRYPTION AS '
SET #procedureHeader = #procedureHeader + REPLICATE(N'-',(#encryptedLength
- LEN(#procedureHeader)))
DECLARE #cnt SMALLINT
DECLARE #decryptedChar NCHAR(1)
DECLARE #decryptedMessage NVARCHAR(MAX)
SET #decryptedMessage = ''
SET #cnt = 1
WHILE #cnt <> #encryptedLength
BEGIN
SET #decryptedChar =
NCHAR(
UNICODE(SUBSTRING(
#encrypted, #cnt, 1)) ^
UNICODE(SUBSTRING(
#procedureHeader, #cnt, 1)) ^
UNICODE(SUBSTRING(
#blankEncrypted, #cnt, 1))
)
SET #decryptedMessage = #decryptedMessage + #decryptedChar
SET #cnt = #cnt + 1
END
SELECT #decryptedMessage
Of course change the dbo.TestDecryption with your procedure name in the script :)
This script works for me, hope it helps
Use
sp_helptext dbo.p_SYS_GetQDNPassword
and
Try to alter the stored procedure and try to get script