This my current code and is working fine.I need the proper syntax to make the fieldname a variable.
For example:
SET #firstname = ''' + #value + ''''
declare #SQL NVARCHAR(4000),#listid nvarchar(50), #value nvarchar(50), #fieldname nvarchar(50)
-- interfering with SELECT statements.
SET NOCOUNT ON;
set #listid = '80000003-1525450413'
set #value = 'dennis4'
set #fieldname = 'firstname'
set #SQL ='Update openquery(QRemote, ''select * from customer WHERE listID = ''''' + #listid + ''''''')
SET firstname = ''' + #value + ''''
EXEC sp_executesql #SQL;
Firstname is a column within Quick Books. All I want is to make it a dynamic parameter. As you can see listID and value are parameters. I would Like to do the following: SET #SQL2 = 'Set #fieldname = ''' + #value + '''' Then I can execute it with EXEC sp_executesql #sql + #sql2.
Related
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX)
--,#DBName VARCHAR(30)
--SET #jobNumber=417133
--SELECT #DBName = DataBaseName,'tdis', #server = '[' + isnull(server,'s-portaldb1') + ']'
--from tdLogging.dbo.tblJobDbLookup where jobnumber = #jobNumber
DROP TABLE #Actual
CREATE TABLE #Actual (
jobnumber INT
,firstNameCounts VARCHAR(25)
,lastNameCounts VARCHAR(25)
,address1Counts VARCHAR(25)
,address2Counts VARCHAR(25)
,cityCounts VARCHAR(25)
,stateCounts VARCHAR(25)
,zipCounts VARCHAR(25)
,inHomeDateCounts VARCHAR(25)
)
SET #sql = 'INSERT INTO #actual (jobnumber,firstNameCounts,lastNameCounts , address1Counts, address2Counts, cityCounts, stateCounts, zipCounts, inHomeDateCounts) '
SET #sql = #sql + ' Select s.jobnumber, count(s.firstName) AS [firstNameCounts], Count (s.lastName) AS [lastNameCounts], Count (s.Address1) As [address1Counts], Count (s.address2)-Count (address2) AS '
SET #sql = #sql + ' [address2Counts], Count (s.City) AS [cityCounts], Count (s.State) AS [stateCounts], Count (s.Zip) AS [zipCounts], Count (jb.inHomeDate) AS [inHomeDateCounts] '
SET #sql = #sql + ' From [s-portaldb1].[tdis_417133].[dbo].[tblStandardFinal] s '
SET #sql = #sql + ' INNER JOIN [s-printstream].[tdSchedule2].[dbo].[tblJobTicketActions] jb '
SET #sql = #sql + ' ON jb.psFlagJobNumber = s.jobNumber '
SET #sql = #sql + ' where jobNumber = #jobNumber '
SET #sql = #sql + ' group by jobNumber '
PRINT #SQL
EXEC sp_executesql #sql
,N'#JobNumber Varchar(25)'
,#JobNumber = 417133;
SELECT *
FROM #Actual
I am trying to get this code to run dynamically and i wanted to have the "[s-portaldb1].[tdis_417133]" come on the run means dynamically.
any help would be greatly appreciated. Thank you
Not sure I know what "come on the run" means, but if you are trying to make the server name dynamic in your dynamic SQL, just add a parameter for your server name and then introduce that to your SQL using something like the following:
DECLARE #ServerName varchar(100) = '[s-portaldb1].[tdis_417133]'
SET #sql = #sql + ' From ' + #Servername + '.[dbo].[tblStandardFinal] s '
I have the following modification of my stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spTMSA_Test_Run]
#TableName nvarchar(200) = 'MyTable',
#Parent int = 1145,
#Name nvarchar(100) = '''Test''',
#KPI nvarchar(max) = '''Test''',
#IDCount int = 1137
AS
BEGIN
EXEC('UPDATE ' + #TableName + ' SET Parent = ' + #Parent + ', Name = ' + #Name + ' , KPI = ' + #KPI + ' WHERE IDCount = ' + #IDCount)
END
This procedure is executed successfully if I gave ''' before and after the string value. In case I left ' before and after the string value it will cause error.
Please help me find the reason why and solution as well. Thanks
This procedure is an open door for SQL injection attacks.
Unless you have a really good reason why you need it to create dynamic SQL, I would suggest avoiding it.
If you can't avoid using dynamic sql, the least you can do is to use quotename to keep your procedure a little safer.
As to the problem you state in your question - just move the ''' to the query body:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spTMSA_Test_Run]
#TableName nvarchar(200) = 'MyTable',
#Parent int = 1145,
#Name nvarchar(100) = 'Test',
#KPI nvarchar(max) = 'Test',
#IDCount int = 1137
AS
BEGIN
EXEC('UPDATE QUOTENAME(' + #TableName + ')
SET Parent = ' + #Parent + ',
Name = ''' + #Name + ''' ,
KPI = ''' + #KPI + '''
WHERE IDCount = ' + #IDCount)
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spTMSA_Test_Run]
#TableName nvarchar(200) = 'MyTable',
#Parent int = 1145,
#Name nvarchar(100) = '''Test''',
#KPI nvarchar(max) = '''Test''',
#IDCount int = 1137
AS
BEGIN
declare #sql nvarchar(4000)
set #sql='UPDATE ' + #TableName + ' SET Parent = ' + #Parent + ', Name = ' + #Name + ' , KPI = ' + #KPI + ' WHERE IDCount = ' + #IDCount
print #sql --find reason in the sql statement
EXEC(#sql)
END
I suggest to use sp_executesql and CAST int to nvarchar before executing query and QUOTENAME the #tablename.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spTMSA_Test_Run]
#TableName nvarchar(200),
#Parent int,
#Name nvarchar(100),
#KPI nvarchar(max),
#IDCount int
AS
BEGIN
DECLARE #sql nvarchar(max)
SELECT #sql = '
UPDATE ' + QUOTENAME(#TableName) + '
SET Parent = ' + CAST(#Parent as nvarchar(10))+ ',
Name = ''' + #Name + ''',
KPI = ''' + #KPI + '''
WHERE IDCount = ' + CAST(#IDCount as nvarchar(10)) + ';'
EXEC sp_executesql #sql
END
I am trying this in SQL Server and it throws an error:
ALTER PROCEDURE [dbo].[GET_TEXT_DETAIL]
#id UNIQUEIDENTIFIER,
#table VARCHAR(255),
#field VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql VARCHAR(200)
SET #sql = 'select ' + QUOTENAME(#field) + ' from ' + QUOTENAME(#table) + ' where ID = ' + QUOTENAME(#id)
EXEC (#sql)
END
I get this error:
Msg 207, Level 16, State 1, Line 1
Invalid column name 'CFC2776A-6EE1-E511-A172-005056A218B0'.
Is there any way to do this so I don't have to make a bunch or procedures to pull text from a bunch of different tables?
QUOTENAME has optional second parameter quote char, so you were close and this could be solved by:
... QUOTENAME(#id, '''')
but the most proper way for this case is passing the parameter:
set #cmd = '
SELECT t.' + QUOTENAME(#field) + '
FROM ' + QUOTENAME(#table) + ' t
WHERE t.ID = #ID'
exec sp_executesql #cmd, N'#ID uniqueidentifier', #ID
And server will be able to reuse plan as #srutzsky mentioned. Because #ID is no longer part of a query text and #cmd text remains the same for different #ID (and same #table+#field).
ALTER PROCEDURE [dbo].[GET_TEXT_DETAIL]
(
#id UNIQUEIDENTIFIER,
#table SYSNAME,
#field SYSNAME
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = '
SELECT ' + QUOTENAME(#field) + '
FROM ' + QUOTENAME(#table) + '
WHERE ID = ''' + CAST(#id AS VARCHAR(36)) + ''''
--PRINT #SQL
EXEC sys.sp_executesql #SQL
END
What is the best way to achieve this
INSERT INTO #TableName (#ColumnNames)
EXEC sp_executesql #SQLResult;
Where #TableName, #ColumnNames, #SQLResult are varchar variables
I am trying to avoid do a separate insert for each table.
The best way is to write (or generate) all reqiured procedures for all table. 23 tables times 4 procedures (insert, update, delete and select) that can be generated automatically is nothing in dev time and pain compared to the so called "generic solution".
It's a path to poor perfomance, unreadable code, sql injection hazard and countless debuging hours.
First of all I appreciate all your comments. And I agree that SQL dynamic is a pain to debug (Thanks God, management studio has this possibility). And, of course there are hundreds of different solutions
I solved it in this way finally, more or less I try to explain why this solution of SQL dynamic. The client uses xlsx spreadsheets to enter certain data, so I read the spreadsheets and I insert the (data depends on the spreadsheet to insert into the proper table). Later the data in the tables are exported to XML to send a third party sofware.
SET #SEL = N'';
DECLARE sel_cursor CURSOR
FOR (SELECT sc.name as field
FROM sys.objects so INNER JOIN sys.columns sc ON so.[object_id]=sc.[object_id]
WHERE so.name= #TableName and sc.name not in ('InitDate', 'EndDate', 'Version', 'Status'));
SET #SEL = ''; set #i = 0;
OPEN sel_cursor
FETCH NEXT FROM sel_cursor INTO #field
WHILE ##FETCH_STATUS = 0
BEGIN
set #sel = #sel + ', '+ #field
set #i = 1;
FETCH NEXT FROM sel_cursor INTO #field
END
CLOSE sel_cursor;
DEALLOCATE sel_cursor;
SET #SQL = N''
SET #SQL = #SQL + N'SELECT * INTO XLImport FROM OPENROWSET'
SET #SQL = #SQL + N'('
SET #SQL = #SQL + N'''Microsoft.ACE.OLEDB.12.0'''+','
SET #SQL = #SQL + N'''Excel 12.0 Xml; HDR=YES;'
SET #SQL = #SQL + N'Database='+#file +''''+ ','
SET #SQL = #SQL + N'''select * from ['+ #SheetName + '$]'''+');'
EXEC sp_executesql #SQL
SET #SQL = N'';
SET #SQL = #SQL + N'
SELECT '+''''+CAST(#initDate AS VARCHAR(10))+'''' +', '+ ''''+CAST(#endDate AS VARCHAR(10))+''''
+ ', '+ CAST(#version AS VARCHAR(2)) +', ' +''''+#status+''''
+ #SEL
+' FROM DBO.XLImport '
DECLARE cols_cursor CURSOR
FOR (Select COLUMN_NAME From INFORMATION_SCHEMA.COLUMNS where table_name = #tableName);
SET #SEL = ''; set #i = 0;
OPEN cols_cursor
FETCH NEXT FROM cols_cursor INTO #field
WHILE ##FETCH_STATUS = 0
BEGIN
set #sel = #sel + #field + ', '
set #i = 1;
FETCH NEXT FROM cols_cursor INTO #field
END
CLOSE cols_cursor;
DEALLOCATE cols_cursor;
SET #SEL = LEFT(#SEL, LEN(#SEL) - 1) -- remove last ,
SET #SQL = N''
SET #SQL = #SQL + N'SELECT * INTO XLImport FROM OPENROWSET'
SET #SQL = #SQL + N'('
SET #SQL = #SQL + N'''Microsoft.ACE.OLEDB.12.0'''+','
SET #SQL = #SQL + N'''Excel 12.0 Xml; HDR=YES;'
SET #SQL = #SQL + N'Database='+#file +''''+ ','
SET #SQL = #SQL + N'''select * from ['+ #SheetName + '$]'''+');'
EXEC sp_executesql #SQL
SET #SQLString =
N'INSERT INTO '+ #TableName + '('+ #SEL +') ' + #SQL;
EXEC sp_executesql #SQLString
Use EXECUTE sp_executesql #sql, here is example:
create proc sp_DynamicExcuteStore
#TableName varchar(50),
#ColumnNames varchar(50),
#SQLResult varchar(max)
as
declare #sql nvarchar(max) = '
INSERT INTO '+#TableName+' ('+#ColumnNames+')
EXEC sp_executesql '+#SQLResult
EXECUTE sp_executesql #sql
go
create proc sp_test
as
select 'test' + convert(varchar,RAND())
go
CREATE TABLE [dbo].[Test](
[text1] [nvarchar](500) NULL
) ON [PRIMARY]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[sp_DynamicExcuteStore]
#TableName = N'Test',
#ColumnNames = N'text1',
#SQLResult = N'proc_test'
SELECT 'Return Value' = #return_value
GO
SELECT TOP 1000 [text1]
FROM [test].[dbo].[Test]
I want to import data from my Excel sheet into my SQL Server 2008 database.
I have an Excel sheet that contains different columns :
Service tag | marque | Type | Serial
FGT3456 | DELL | UC | Optiplex 760
and my table has the same structure, but instead of varchar values, I have foreign keys (the IDs)
Example (table material)
Service tag | marque| Type | Serial
FGT3456 | 1 | 18 | 27
What I want to do is to fetch into the column marque in the Excel sheet, get all the marque values, compare the values to those in my table, get all them IDs and in the end insert the Ids into my table material.
I tried this code but it's showing an error
Incorrect syntax near the keyword 'SELECT'.
Incorrect syntax near ')'.
Invalid object name 'SQL'.
This is my code
ALTER PROCEDURE [dbo].[spx_Import]
#SheetName varchar(20),
#FilePath varchar(100),
#HDR varchar(3),
#TableName varchar(50)
AS
BEGIN
DECLARE #SQL nvarchar(1000)
DECLARE #SQL1 nvarchar(1000)
DECLARE #SQL2 nvarchar(1000)
SET #SQL = 'SELECT idMarque FROM MarqueMateriel WHERE marque = SELECT (marque) FROM OPENDATASOURCE'
SET #SQL1 = 'INSERT INTO Material (Service tag) SELECT (service tag) FROM OPENDATASOURCE'
SET #SQL2 = 'INSERT INTO Material (MARQUE) SELECT * FROM '+#SQL''
SET #SQL = #SQL + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL = #SQL + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL = #SQL + #HDR + ''''''')...['
SET #SQL = #SQL + #SheetName + ']'
SET #SQL1 = #SQL1 + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL1 = #SQL1 + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL1 = #SQL1 + #HDR + ''''''')...['
SET #SQL1 = #SQL1 + #SheetName + ']'
SET #SQL1 = #SQL2 + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL1 = #SQL2 + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL1 = #SQL2 + #HDR + ''''''')...['
SET #SQL1 = #SQL2 + #SheetName + ']'
EXEC sp_executesql #SQL
EXEC sp_executesql #SQL1
EXEC sp_executesql #SQL2
END
In the first query #SQL, I retrieve all IDs from the table Material where the name(marque) equals to those in the Excel sheet.
In the 2nd query, #SQL1, I insert the serviceTag values from the Excel sheet into the table
In the last one #SQL2, I insert into the table material the IDs retrieved from the first query
Is my logic correct ?? Is this how I should proceed ?? Please I need help !!
Try changing this line:
SET #SQL2 = 'INSERT INTO Material (MARQUE) SELECT * FROM '+#SQL''
To this - i.e. wrap the #SQL with brackets:
SET #SQL2 = 'INSERT INTO Material (MARQUE) SELECT * FROM (' + #SQL + ')'
I found the solution, it's quite easy and should've think of it from the first time . I imported all the data from my excel sheet into a temp table, and fetch into my mark table get all IDs and insert them directly into my material table.
This is how I achieved this
USE [AxaStock]
GO
ALTER PROCEDURE [dbo].[spx_Import]
#SheetName varchar(20),
#FilePath varchar(100),
#HDR varchar(3),
#TableName varchar(50)
AS
BEGIN
DECLARE #SQL nvarchar(1000)
DECLARE #QUERY nvarchar(1000)
SET #SQL = 'INSERT INTO ESSAIE (serviceTag, periodeGarantie, periodeLeasing, marque, designation, serie, entite, dateDG, nCommande) SELECT serviceTag, periodeGarantie, periodeLeasing, marque, designation, serie, entite, dateDG, nCommande FROM OPENDATASOURCE'
SET #QUERY = 'insert into Materiel (serviceTag, idMarque, idTypeMateriel, idSerieMateriel) select distinct serviceTag, idMarque, idTypeMateriel, '+
'idSerieMateriel from ESSAIEIMPORT ess, MarqueMateriel mm, Serie s, TypeMateriel tm where mm.marque=ess.marque and tm.nomType=ess.designation and '+
's.serieMateriel=ess.serie delete from ESSAIEIMPORT'
SET #SQL = #SQL + '(''Microsoft.ACE.OLEDB.12.0'',''Data Source='
SET #SQL = #SQL + #FilePath + ';Extended Properties=''''Excel 12.0;HDR='
SET #SQL = #SQL + #HDR + ''''''')...['
SET #SQL = #SQL + #SheetName + ']'
EXEC sp_executesql #SQL
EXEC sp_executesql #QUERY
END