I create a stored procedure in which I am using a dynamic query. The query will get data from my query and insert into my temp table and in last I select data from #temp table.
This is my stored procedure:
ALTER PROCEDURE uspSearchEmployee
#Name varchar(50)= null,
#EmpNumber varchar(50)=null,
#Location Varchar(50)=null,
#position varchar(50)=null,
#partialmatch bit ,
#partialmatch2 bit,
#partialmatch3 bit
AS
BEGIN
declare #wheresql varchar(max)
if (#Name is not null)
BEGIN
if(#partialmatch=1)
set #wheresql=' where EmpName like ''%'+ #Name + ''''
else
set #wheresql=' where EmpName = ' +#Name
END
IF(#Name is null AND #EmpNumber IS NOT NULL )
BEGIN
if(#partialmatch2=1)
set #wheresql=' where EmployeeNum like ''%' + #EmpNumber + ''''
else
set #wheresql=' where EmployeeNum = '+#EmpNumber
END
IF(#Name is NOT null AND #EmpNumber IS NOT NULL )
BEGIN
if(#partialmatch2=1)
set #wheresql=#wheresql+' AND EmployeeNum like ''%'+#EmpNumber +''''
else
set #wheresql=#wheresql+' AND EmployeeNum ='+#EmpNumber
END
--3rd case
IF(#Name is null AND #EmpNumber IS NULL AND #Location IS NOT NULL )
BEGIN
if(#partialmatch3=1)
set #wheresql=' where Location like ''%' +#Location + ''''
else
set #wheresql=' where Location = ' +#Location
END
IF((#Name is NOT null OR #EmpNumber IS NOT NULL) AND #Location IS NOT NULL )
BEGIN
if(#partialmatch3=1)
set #wheresql=#wheresql+ ' AND Location like ''%'+#EmpNumber + ''''
else
set #wheresql=#wheresql+' AND Location ='+#EmpNumber
END
IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
(
EmpId int,
EmpName varchar(40),
Location varchar(50)null,
City varchar(40)null,
STPROV varchar(15)null,
EmergencyPhone varchar(50)null,
ZIPPOSTAL varchar(10) null,
Home_Phone varchar(25)null,
Country varchar(25) null,
Department varchar(50) null,
Position varchar(50) null,
WorkCompCode varchar(50) null,
Active bit null
)
set #wheresql=' INSERT INTO #temp
SELECT EmpId,EmpName,Location,City,STPROV,EmergencyPhone,ZIPPOSTAL,Home_Phone,Country,Department
Position,WorkCompCode,Active
from employee ' + ISNULL(#wheresql, '')
PRINT #wheresql
EXECUTE sys.sp_executesql #wheresql
Select * FROM #temp
END
When I execute I get error message
Msg 1087, Level 15, State 2, Line 1
Must declare the table variable "#temp".
What am I doing wrong in this query?
Regards
Try to use temporary tables -
ALTER PROCEDURE dbo.uspSearchEmployee
#Name VARCHAR(50) = NULL,
#EmpNumber VARCHAR(50) = NULL,
#Location VARCHAR(50) = NULL,
#position VARCHAR(50) = NULL,
#partialmatch BIT,
#partialmatch2 BIT,
#partialmatch3 BIT
AS BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX)
IF #Name IS NOT NULL
BEGIN
IF (#partialmatch = 1)
SET #SQL = ' WHERE EmpName LIKE ''%' + #Name + ''''
ELSE
SET #SQL = ' WHERE EmpName = ' + #Name
END
IF #Name IS NULL AND #EmpNumber IS NOT NULL
BEGIN
IF (#partialmatch2 = 1)
SET #SQL = ' WHERE EmployeeNum LIKE ''%' + #EmpNumber + ''''
ELSE
SET #SQL = ' WHERE EmployeeNum = ' + #EmpNumber
IF (#partialmatch2 = 1)
SET #SQL = #SQL + ' AND EmployeeNum LIKE ''%' + #EmpNumber + ''''
ELSE
SET #SQL = #SQL + ' AND EmployeeNum =' + #EmpNumber
END
IF #Name IS NULL AND #EmpNumber IS NULL AND #Location IS NOT NULL
BEGIN
IF (#partialmatch3 = 1)
SET #SQL = ' WHERE Location LIKE ''%' + #Location + ''''
ELSE
SET #SQL = ' WHERE Location = ' + #Location
END
IF (#Name IS NOT NULL OR #EmpNumber IS NOT NULL) AND #Location IS NOT NULL
BEGIN
IF (#partialmatch3 = 1)
SET #SQL = #SQL + ' AND Location LIKE ''%' + #EmpNumber + ''''
ELSE
SET #SQL = #SQL + ' AND Location =' + #EmpNumber
END
IF OBJECT_ID('tempdb.dbo.#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
(
EmpId INT,
EmpName VARCHAR(40),
Location VARCHAR(50) NULL,
City VARCHAR(40) NULL,
STPROV VARCHAR(15) NULL,
EmergencyPhone VARCHAR(50) NULL,
ZIPPOSTAL VARCHAR(10) NULL,
Home_Phone VARCHAR(25) NULL,
Country VARCHAR(25) NULL,
Department VARCHAR(50) NULL,
Position VARCHAR(50) NULL,
WorkCompCode VARCHAR(50) NULL,
Active BIT NULL
)
SET #SQL = '
INSERT INTO #temp
SELECT EmpId,EmpName,Location,City,STPROV,EmergencyPhone,ZIPPOSTAL,Home_Phone,Country,Department,Position,WorkCompCode,Active
FROM dbo.employee ' + ISNULL(#SQL, '')
PRINT #SQL
EXEC sys.sp_executesql #SQL
SELECT * FROM #temp
END
Related
I have an ETL package built in SSIS that I'm trying to run but I'm getting this error, mainly the third one:
The part in the package that is giving the error is built like this:
The specific component that is causing the error is the call to the SP and this are the parameters:
The parameters are translated to:
The parameters come from the query done at the start of the data flow:
The error mentions invalid column 'P2' the only column that takes this value is SG_PLANO_CTB.
This is the SP that's being used:
USE [SISF_DW_REPORTING]
GO
/****** Object: StoredProcedure [dbo].[SP_INSERT_EAF_MEMBER] Script Date: 8/10/2018 11:22:07 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Batch submitted through debugger: SQLQuery64.sql|7|0|C:\Users\SQL_AD~1.CMC\AppData\Local\Temp\3\~vs4CBB.sql
-- Batch submitted through debugger: SQLQuery29.sql|7|0|C:\Users\SQL_AD~1.CMC\AppData\Local\Temp\3\~vs8A81.sql
-- =============================================
-- Author:
-- Create date:
-- Description: This stored procedure creates the Early Arriving Fact for a given reference table
-- =============================================
ALTER PROCEDURE [dbo].[SP_INSERT_EAF_MEMBER]
#TABLE NVARCHAR(50)
,#CD_REF NVARCHAR(50)
,#LOG_ID INT
,#ID_SK_COMPOSITE NVARCHAR(50) = NULL
,#COL_SK_COMPOSITE NVARCHAR(50) = NULL
,#DT_LOAD_DATE INT = NULL
,#TABLE_FCT NVARCHAR(50) = NULL
,#DEBUG BIT = 0
AS
BEGIN
SET NOCOUNT ON
IF 1=2
BEGIN
SELECT CAST(NULL AS INT) AS ID_REF
,CAST(NULL AS NVARCHAR(50)) AS DS_TBL_NAME
,CAST(NULL AS NVARCHAR(50)) AS CD_SRCE_SYTM
,CAST(NULL AS INT) AS LOG_ID
,CAST(NULL AS INT) AS DT_LOAD_DATE
,CAST(NULL AS NVARCHAR(50)) AS DS_TBL_FCT_NAME
END
--****************************************************
SET #TABLE = LTRIM(RTRIM(#TABLE))
SET #CD_REF = LTRIM(RTRIM(#CD_REF))
SET #TABLE_FCT = LTRIM(RTRIM(#TABLE_FCT))
--****************************************************
DECLARE #ID_INT_EAF INT
DECLARE #ID_EAF NVARCHAR(100)
DECLARE #DS_EAF NVARCHAR(100)
DECLARE #DT_INT_EAF NVARCHAR(100)
DECLARE #DT_DAT_EAF NVARCHAR(100)
DECLARE #CD_INT_EAF NVARCHAR(100)
DECLARE #CD_VAR_EAF NVARCHAR(100)
DECLARE #FL_EAF NVARCHAR(4)
DECLARE #NR_INT_EAF NVARCHAR(100)
DECLARE #NR_VAR_EAF NVARCHAR(100)
DECLARE #QT_EAF NVARCHAR(100)
DECLARE #VL_EAF NVARCHAR(100)
DECLARE #DMS_EAF NVARCHAR(100)
DECLARE #GPS_EAF NVARCHAR(100)
DECLARE #WGS_EAF NVARCHAR(100)
DECLARE #DT_CRTN NVARCHAR(100)
DECLARE #QUERY_FCT_LOAD_EAF VARCHAR(7000)
DECLARE #QUERY_REF_EAF VARCHAR(7000)
DECLARE #SG_EAF NVARCHAR(100)
DECLARE #HR_EAF NVARCHAR(100)
SET #ID_EAF = '-1'
SET #DS_EAF = '''EAF Member ('+#CD_REF+')'''
SET #DT_INT_EAF = '-1'
SET #DT_DAT_EAF = '''1900-01-01'''
SET #CD_VAR_EAF = ''''+#CD_REF+''''
SET #CD_INT_EAF = '-1'
SET #FL_EAF = '''-1'''
SET #NR_INT_EAF = '0'
SET #NR_VAR_EAF = '''EAF Member'''
SET #QT_EAF = '''0'''
SET #VL_EAF = '''0'''
SET #DMS_EAF = '''EAF Member'''
SET #GPS_EAF = '''EAF Member'''
SET #WGS_EAF = '-1'
SET #DT_CRTN = CONVERT(NVARCHAR(8),GETDATE(),112)
SET #SG_EAF = '''EAF'''
SET #HR_EAF = '''00:00:00'''
-- Declare auxiliary variables
DECLARE #TABLE_NAME NVARCHAR(50), #COLUMN_NAME NVARCHAR(100), #EAF_VALUE NVARCHAR(100)
DECLARE #INSERT NVARCHAR(3000), #VALUES NVARCHAR(3000), #WHERE NVARCHAR(1000), #IDENTITY_ON NVARCHAR(1000), #IDENTITY_OFF NVARCHAR(1000)
DECLARE #STATEMENT VARCHAR(7000)
SET #IDENTITY_ON = 'SET IDENTITY_INSERT ' + #TABLE + ' ON;'
SET #IDENTITY_OFF = 'SET IDENTITY_INSERT ' + #TABLE + ' OFF;'
SET #INSERT = 'INSERT INTO ' + #TABLE + ' ('
SET #VALUES = ' SELECT '
BEGIN
IF #COL_SK_COMPOSITE IS NULL
SET #WHERE = ' WHERE NOT EXISTS (SELECT 1 FROM ' + #TABLE + ' WHERE CD_' + SUBSTRING(#TABLE,9,LEN(#TABLE)) + ' = '''+#CD_REF+''');'
ELSE
SET #WHERE = ' WHERE NOT EXISTS (SELECT 1 FROM ' + #TABLE + ' WHERE CD_' + SUBSTRING(#TABLE,9,LEN(#TABLE)) + ' = '''+#CD_REF+''' AND ' + #COL_SK_COMPOSITE + ' = ' + #ID_SK_COMPOSITE + ');'
END
DECLARE TABLE_COLUMNS CURSOR FOR
SELECT
C.TABLE_NAME
,C.COLUMN_NAME
,CASE
WHEN #COL_SK_COMPOSITE IS NOT NULL AND LEFT(C.NEW_COLUMN_NAME,2) LIKE 'ID' AND C.NEW_COLUMN_NAME NOT LIKE 'ID_'+SUBSTRING(C.TABLE_NAME,5,LEN(C.TABLE_NAME)) AND C.NEW_COLUMN_NAME NOT LIKE 'ID_'+SUBSTRING(C.TABLE_NAME,9,LEN(C.TABLE_NAME))
THEN #ID_SK_COMPOSITE
WHEN #COL_SK_COMPOSITE IS NULL AND LEFT(C.NEW_COLUMN_NAME,2) LIKE 'ID' AND C.NEW_COLUMN_NAME NOT LIKE 'ID_'+SUBSTRING(C.TABLE_NAME,5,LEN(C.TABLE_NAME)) AND C.NEW_COLUMN_NAME NOT LIKE 'ID_'+SUBSTRING(C.TABLE_NAME,9,LEN(C.TABLE_NAME))
THEN #ID_EAF
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'DS'
THEN #DS_EAF
WHEN C.NEW_COLUMN_NAME = 'DT_START' THEN '''1900-01-01'''
WHEN C.NEW_COLUMN_NAME = 'DT_END' THEN '''9999-12-31'''
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'DT' THEN
CASE
WHEN C.NEW_COLUMN_NAME LIKE 'DT_CRTN' THEN #DT_CRTN
WHEN C.DATA_TYPE LIKE 'int' THEN #DT_INT_EAF
ELSE #DT_DAT_EAF END
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'CD' THEN
CASE WHEN C.DATA_TYPE LIKE 'int' THEN #CD_INT_EAF ELSE #CD_VAR_EAF END
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'FL'
THEN #FL_EAF
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'NR' THEN
CASE
WHEN C.DATA_TYPE LIKE 'int' THEN #NR_INT_EAF
WHEN C.DATA_TYPE LIKE 'numeric' THEN #NR_INT_EAF
ELSE #NR_VAR_EAF END
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'QT'
THEN #QT_EAF
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'VL'
THEN #VL_EAF
WHEN LEFT(C.NEW_COLUMN_NAME,3) LIKE 'DMS'
THEN #DMS_EAF
WHEN LEFT(C.NEW_COLUMN_NAME,3) LIKE 'GPS'
THEN #GPS_EAF
WHEN LEFT(C.NEW_COLUMN_NAME,3) LIKE 'WGS'
THEN #WGS_EAF
WHEN C.NEW_COLUMN_NAME = 'CTL_LOG_EAF'
THEN '1'
WHEN LEFT(C.NEW_COLUMN_NAME,7) LIKE 'CTL_LOG'
THEN CAST(#LOG_ID AS NVARCHAR(50))
WHEN #COL_SK_COMPOSITE IS NOT NULL AND LEFT(C.NEW_COLUMN_NAME,2) LIKE 'SG'
THEN #ID_SK_COMPOSITE
WHEN #COL_SK_COMPOSITE IS NULL AND LEFT(C.NEW_COLUMN_NAME,2) LIKE 'SG'
THEN #SG_EAF
WHEN LEFT(C.NEW_COLUMN_NAME,2) LIKE 'HR'
THEN #HR_EAF
ELSE ''
END EAF_VALUE
FROM
(
SELECT
TABLE_NAME
,COLUMN_NAME
,CASE WHEN LEFT(COLUMN_NAME,2) LIKE 'X_' THEN SUBSTRING(COLUMN_NAME,3,LEN(COLUMN_NAME)) ELSE COLUMN_NAME END AS NEW_COLUMN_NAME
,DATA_TYPE
,ORDINAL_POSITION
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME NOT LIKE 'ID_'+SUBSTRING(TABLE_NAME,9,LEN(TABLE_NAME))
) C
INNER JOIN
INFORMATION_SCHEMA.TABLES T
ON C.TABLE_NAME = T.TABLE_NAME
WHERE
T.TABLE_TYPE LIKE 'BASE TABLE'
AND T.TABLE_NAME LIKE #TABLE
ORDER BY
TABLE_NAME, ORDINAL_POSITION
OPEN TABLE_COLUMNS
FETCH NEXT FROM TABLE_COLUMNS INTO #TABLE_NAME, #COLUMN_NAME, #EAF_VALUE;
WHILE ##FETCH_STATUS = 0
BEGIN
IF #COLUMN_NAME <> ''
BEGIN
SET #INSERT = #INSERT + #COLUMN_NAME + ', '
END
IF #EAF_VALUE <> ''
BEGIN
SET #VALUES = #VALUES + #EAF_VALUE + ', '
END
FETCH NEXT FROM TABLE_COLUMNS INTO #TABLE_NAME, #COLUMN_NAME, #EAF_VALUE;
END
CLOSE TABLE_COLUMNS
DEALLOCATE TABLE_COLUMNS
-- Final columns
SET #INSERT = LEFT(#INSERT,LEN(#INSERT)-1) + ')'
SET #VALUES = LEFT(#VALUES,LEN(#VALUES)-1)
SET #QUERY_FCT_LOAD_EAF = 'INSERT INTO FCT_LOAD_EAF (ID_LOAD_DATE, ID_CRTN_DATE, DS_REF_TABLE_NAME, DS_FCT_TABLE_NAME, CD_SRCE_SYTM,CTL_LOG_INSERT) SELECT '+CAST(#DT_LOAD_DATE AS NVARCHAR(8))+', '+#DT_CRTN+', '''+#TABLE+''', '''+#TABLE_FCT+''', '''+#CD_REF+''', '+CAST(#LOG_ID AS NVARCHAR(50))+' '+#WHERE
IF #DEBUG = 1 BEGIN SELECT #QUERY_FCT_LOAD_EAF END ELSE BEGIN EXECUTE(#QUERY_FCT_LOAD_EAF) END
PRINT #QUERY_FCT_LOAD_EAF
SET #STATEMENT = #INSERT + #VALUES + #WHERE
IF #DEBUG = 1 BEGIN SELECT #STATEMENT END ELSE BEGIN EXECUTE(#STATEMENT) END
PRINT #STATEMENT
IF LEFT(#TABLE,2) = 'X_'
BEGIN
SET #QUERY_REF_EAF = 'SELECT X_ID_'+SUBSTRING(#TABLE,7,LEN(#TABLE))+' AS ID_REF, ''' + #TABLE + ''' AS DS_TBL_NAME, CAST(X_CD_SRCE_SYTM AS NVARCHAR(50)) AS CD_SRCE_SYTM, '+CAST(#LOG_ID AS NVARCHAR(50))+' AS LOG_ID, '+CAST(#DT_LOAD_DATE AS NVARCHAR(8))+' AS DT_LOAD_DATE , ''' + #TABLE_FCT + ''' AS DS_TBL_FCT_NAME FROM '+#TABLE+' WHERE X_CD_SRCE_SYTM LIKE '''+#CD_REF+''''
IF #DEBUG = 1 BEGIN SELECT #QUERY_REF_EAF END ELSE BEGIN EXECUTE(#QUERY_REF_EAF) END
PRINT #QUERY_REF_EAF
END
ELSE
BEGIN
SET #QUERY_REF_EAF = 'SELECT ID_'+SUBSTRING(#TABLE,5,LEN(#TABLE))+' AS ID_REF, ''' + #TABLE + ''' AS DS_TBL_NAME, CAST(CD_SRCE_SYTM AS NVARCHAR(50)) AS CD_SRCE_SYTM, '+CAST(#LOG_ID AS NVARCHAR(50))+' AS LOG_ID, '+CAST(#DT_LOAD_DATE AS NVARCHAR(8))+' AS DT_LOAD_DATE, ''' + #TABLE_FCT + ''' AS DS_TBL_FCT_NAME FROM '+#TABLE+' WHERE CD_SRCE_SYTM LIKE '''+#CD_REF+''''
IF #DEBUG = 1 BEGIN SELECT #QUERY_REF_EAF END ELSE BEGIN EXECUTE(#QUERY_REF_EAF) END
PRINT #QUERY_REF_EAF
END
SET NOCOUNT OFF
END
I tried debugging the SP but I can't figure out where he builds the query that uses 'P2' as a column and not as value of the column SG_PLANO_CTB
Edit: I decided to log the parameters that were being used. Found out that the one causing the call causing the error is
exec SISF_DW_REPORTING..SP_INSERT_EAF_MEMBER 'REF_FIN_RUBRICA','11.1.1', 210999, 'P2', 'SG_PLANO_CTB'
And the query that's causing the error is
INSERT INTO REF_FIN_RUBRICA (CD_RUBRICA, DS_RUBRICA, CD_KEY, CD_PARENT, SG_PLANO_CTB, DT_START, DT_END, CTL_LOG_UPDATE, CTL_LOG_EAF) SELECT '11.1.1', 'EAF Member (11.1.1)', '11.1.1', '11.1.1', P2, '1900-01-01', '9999-12-31', 210999, 1 WHERE NOT EXISTS (SELECT 1 FROM REF_FIN_RUBRICA WHERE CD_RUBRICA = '11.1.1' AND SG_PLANO_CTB = P2);
I would guess the string delimitators aren't being added in the cursor somewhere. Can't see where though.
I tried to step through your generated proc logically, and I think I see where the issue lies. The call that's causing the error, exec SISF_DW_REPORTING..SP_INSERT_EAF_MEMBER 'REF_FIN_RUBRICA','11.1.1', 210999, 'P2', 'SG_PLANO_CTB' should probably be changed to:
exec SISF_DW_REPORTING..SP_INSERT_EAF_MEMBER 'REF_FIN_RUBRICA','11.1.1', 210999, '''P2''', 'SG_PLANO_CTB'
It looks like the dynamic sql generation takes the value of one of your input variables and uses that in the query string it builds. If your query needs a string value, you have to additionally double delimit it.
I'm trying to write a stored procedure in SQL Server that gets the columns as parameters. The user will select the column name from a combo box and will write the searched value for that column on a textbox.
I've been searching how to do this and so far i have this:
ALTER PROCEDURE [dbo].[SP_Select_TBL_Folio]
#cant int,
#Column1 nvarchar(50),
#Value1 nvarchar(50),
#Column2 nvarchar(50),
#Value2 nvarchar(50),
#Column3 nvarchar(50),
#Value3 nvarchar(50)
AS
BEGIN
declare #query nvarchar (max)
SET NOCOUNT ON;
if #cant = 1
BEGIN
set #query = 'SELECT * FROM TBL_Folio WHERE ' + #Column1 + ' LIKE '+ #Value1 + ' ORDER BY 1 DESC';
exec sp_executesql #query, N' '
END
else
BEGIN
if #cant = 2
BEGIN
set #query = 'SELECT * FROM TBL_Folio WHERE ' + #Column1 + ' LIKE '+ #Value1 + ' AND ' + #Column2 + ' LIKE '+ #Value2 + ' ORDER BY 1 DESC';
exec sp_executesql #query, N' '
END
ELSE
if #cant = 3
BEGIN
set #query = 'SELECT * FROM TBL_Folio WHERE ' + #Column1 + ' LIKE '+ #Value1 + ' AND ' + #Column2 + ' LIKE '+ #Value2 + ' AND ' + #Column3 + ' LIKE '+ #Value3 + ' ORDER BY 1 DESC';
exec sp_executesql #query, N' '
END
END
END
The user can send 1 to 3 values, for that I have the parameter #cant, this code works but I want to know if there is a better way to do this or how can I improve this stored procedure.
I think what you have is fine if you need to do it in an SP rather than client side. I would probabably initialize the query to the 'select * from TBL_Folio" and then append the LIKES after each if. I would also caution against using SELECT * so your client side doesn't blow up if a field gets added to the table.
If you have a need to check a variable number of fields rather than just up to 3, you can do a table-valued parameter and build up your query by looping through. Here is an example:
ALTER PROCEDURE [dbo].[GetFilteredInvoices]
#FilterColumns ColumnValueType READONLY
AS
BEGIN
SET NOCOUNT ON;
declare #columnName varchar(50), #columnValue varchar(MAX), #query nvarchar(MAX), #count int
set #query='SELECT InvoiceNumber, InvoiceDate, Customer from Invoices '
set #count=0
set #columnName=''
while exists(select * from #FilterColumns where ColumnName>#ColumnName)
begin
set #columnName=(select min(ColumnName) from #FilterColumns where ColumnName>#columnName)
if #count=0
set #query=#query+'WHERE '
else
set #query=#query+'AND '
set #query=#query+ (select ColumnName+' Like ''%'+ColumnValue+'%'' ' from #filterColumns where ColumnName=#columnName)
set #count=#count+1
end
exec sp_executesql #query
END
Here is the table valued type I used:
CREATE TYPE [dbo].[ColumnValueType] AS TABLE(
[ColumnName] [varchar](50) NULL,
[ColumnValue] [varchar](max) NULL
)
GO
Now this will take any number of columns and values to apply the filter.
Here is an example call to the procedure:
DECLARE #RC int
DECLARE #FilterColumns [dbo].[ColumnValueType]
insert into #filterColumns
Values('InvoiceNumber','345')
,('Customer','67')
EXECUTE #RC = [dbo].[GetFilteredInvoices]
#FilterColumns
I think you can perhaps improve the way that you handle your input parameters by getting rid of the #cant parameter. You can also improve the way that you build up the conditions, at the moment you are not handling the situations where only #Column2 and #Value2 or only #Column3 and #Value3 is set (perhaps it is not needed in your case, but it is still good practice to handle these types of scenarios)
CREATE PROCEDURE SP_Select_TBL_Folio
#Column1 NVARCHAR(50) = NULL,
#Value1 NVARCHAR(50) = NULL,
#Column2 NVARCHAR(50) = NULL,
#Value2 NVARCHAR(50) = NULL,
#Column3 NVARCHAR(50) = NULL,
#Value3 NVARCHAR(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#P1 NVARCHAR(500),
#P2 NVARCHAR(500),
#P3 NVARCHAR(500),
#SQL NVARCHAR(MAX)
IF (#Column1 IS NULL OR #Column1 = '') AND (#Value1 IS NULL OR #Value1 = '')
BEGIN
-- This will build up dynamic SQL to always select records even if #Column1
-- and #Value1 is not set. This obvisously all depends on your requirements
-- and if you still need to select records if the parameters are not set, otherwise
-- it can be changed to ' WHERE ThePrimaryKeyColumn = 0'
SET #P1 = ' WHERE ThePrimaryKeyColumn > 0'
END
ELSE
BEGIN
SET #P1 = 'WHERE ' + #Column1 + ' LIKE ' + '''' + #Value1 + ''''
END
IF (#Column2 IS NULL OR #Column2 = '') AND (#Value2 IS NULL OR #Value2 = '')
BEGIN
SET #P2 = ''
END
ELSE
BEGIN
SET #P2 = ' AND ' + #Column2 + ' LIKE ' + '''' + #Value2 + ''''
END
IF (#Column3 IS NULL OR #Column3 = '') AND (#Value3 IS NULL OR #Value3 = '')
BEGIN
SET #P3 = ''
END
ELSE
BEGIN
SET #P3 = ' AND ' + #Column3 + ' LIKE ' + '''' + #Value3 + ''''
END
SET #SQL = 'SELECT * FROM TBL_Folio
[P1]
[P2]
[P3]'
-- Here we set all the conditions
SET #SQL = REPLACE(#SQL, '[P1]', #P1);
SET #SQL = REPLACE(#SQL, '[P2]', #P2);
SET #SQL = REPLACE(#SQL, '[P3]', #P3);
-- This will be replaced by EXEC(#SQL)
PRINT #SQL
END
So now you can for instance execute
EXEC SP_Select_TBL_Folio
which will give you
SELECT * FROM TBL_Folio
WHERE ThePrimaryKeyColumn > 0
or you can execute
EXEC SP_Select_TBL_Folio 'Column1','Value1'
which will give you
SELECT * FROM TBL_Folio
WHERE Column1 LIKE 'Value1'
or you can execute
EXEC SP_Select_TBL_Folio NULL,NULL,'Column2','Value2'
which will give you
SELECT * FROM TBL_Folio
WHERE ThePrimaryKeyColumn > 0
AND Column2 LIKE 'Value2'
I'm not going to list all the permutations, I'm sure you get my point.
I would like to execute this query in a stored procedure, but I get 2 errors :
a database of USE instruction not allowed in a procedure, function, or
a trigger.
Incorrect syntax near the keyword 'CREATE'. (Microsoft SQL
Server, Error: 154).
My code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_copytable_TEST]
#SourceServer nvarchar(255),
#SourceDatabase nvarchar(255),
#SourceSchema nvarchar(255),
#DestinationSchema nvarchar(255)
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#SQL NVARCHAR(MAX),
#id uniqueidentifier = NEWID()
BEGIN
IF NOT EXISTS (SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'TablesLog_TEST')
CREATE TABLE [dbo].[TablesLog_TEST]
(
[id] [uniqueidentifier] NOT NULL,
[SourceServer] [nvarchar](255) NULL,
[SourceDatabase] [nvarchar](255) NULL,
[SourceSchema] [nvarchar](255) NULL,
[source] [nvarchar](max) NULL,
[destination] [nvarchar](255) NULL,
[timestamp] [datetime] NULL,
[message] [nvarchar](max) NULL,
[type] [smallint] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
INSERT INTO dbo.TablesLog_TEST
SELECT
#id, #SourceServer, #SourceDatabase, #SourceSchema,
'GetAllTables', #DestinationSchema, CURRENT_TIMESTAMP,
'Start Copy', 1
BEGIN TRY
INSERT INTO dbo.TablesLog_TEST
SELECT
#id, #SourceServer, #SourceDatabase, #SourceSchema,
'GetAllTables', #DestinationSchema, CURRENT_TIMESTAMP,
'try 1', 1
-- Create destination schema if it doesn't exist
SELECT #SQL = N'IF NOT EXISTS (SELECT * FROM [' + #SourceDatabase + '].SYS.SCHEMAS WHERE NAME = [' + #DestinationSchema + '])
BEGIN
SELECT #SQL = N'USE ['+ #SourceDatabase +'];
EXEC(''CREATE SCHEMA '+ #DestinationSchema +' '')'
EXEC sp_executesql #SQL
END'
EXEC sp_executesql #SQL
END TRY
BEGIN CATCH
INSERT INTO dbo.TablesLog_TEST
SELECT #id, #SourceServer, #SourceDatabase, #SourceSchema,
'GetAllTables', #DestinationSchema, CURRENT_TIMESTAMP,
'ERROR: ' + ERROR_MESSAGE(), 0
END CATCH
--Return value:
SELECT 1;
END
Someone can help me please?
Best regards
Slim
Slim
This code will work
SELECT #SQL = N'IF NOT EXISTS (SELECT * FROM [' + #SourceDatabase + '].SYS.SCHEMAS WHERE NAME = ''' + #DestinationSchema + ''')
BEGIN
DECLARE #SQL NVARCHAR(MAX);
SELECT #SQL = N''USE ['+ #SourceDatabase +'];
EXEC(''''CREATE SCHEMA '+ #DestinationSchema +' '''')''
EXEC sp_executesql #SQL
END'
EXEC sp_executesql #SQL
As Sandip spotted you need to declare the #SQL variable in your dynamic code. When you use sp_executesql to run the dynamic code, it is effectively running in isolation to your main stored proc, and thus knows nothing about any variables declared previously. You'll see I've added a few more single quotes to get everything working; also replaced the [] in the SELECT statement so that #DestinationSchema appears as text, and not a column name.
As an aside, do you know how to use the debug tools in SQL Server Management Studio? Type the following
EXEC usp_copytable_TEST 'SourceServer', 'SourceDatabase', 'SourceSchema', 'DestinationSchema'
on its own in a new query window. Instead of pressing F5 to execute, press ALT+F5, this will invoke a debug session and you can now step through the code line by line, watch variables and so on. You'll find this very helpful as you can see the values of your dynamic SQL strings.
Try This:
USE [CORE]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[usp_copytable_TEST]
#SourceServer nvarchar(255),
#SourceDatabase nvarchar(255),
#SourceSchema nvarchar(255),
#DestinationSchema nvarchar(255)
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#SQL NVARCHAR(MAX),
#id uniqueidentifier = NEWID()
BEGIN
If NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'TablesLog_TEST')
CREATE TABLE [dbo].[TablesLog_TEST](
[id] [uniqueidentifier] NOT NULL,
[SourceServer] [nvarchar](255) NULL,
[SourceDatabase] [nvarchar](255) NULL,
[SourceSchema] [nvarchar](255) NULL,
[source] [nvarchar](max) NULL,
[destination] [nvarchar](255) NULL,
[timestamp] [datetime] NULL,
[message] [nvarchar](max) NULL,
[type] [smallint] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
INSERT INTO dbo.TablesLog_TEST SELECT #id, #SourceServer,#SourceDatabase, #SourceSchema, 'GetAllTables', #DestinationSchema, CURRENT_TIMESTAMP, 'Start Copy', 1
BEGIN TRY
INSERT INTO dbo.TablesLog_TEST SELECT #id, #SourceServer,#SourceDatabase, #SourceSchema, 'GetAllTables', #DestinationSchema, CURRENT_TIMESTAMP, 'try 1', 1
-- Create destination schema if it doesn't exist
SELECT #SQL = N'IF NOT EXISTS (SELECT * FROM [' + #SourceDatabase + '].SYS.SCHEMAS WHERE NAME = [' + #DestinationSchema + '])
BEGIN
SELECT #SQL = N''USE ['+ #SourceDatabase +'];
EXEC(''CREATE SCHEMA '+ #DestinationSchema +' '')''
EXEC sp_executesql #SQL
END'
EXEC sp_executesql #SQL
END TRY
BEGIN CATCH
INSERT INTO dbo.TablesLog_TEST SELECT #id, #SourceServer,#SourceDatabase, #SourceSchema, 'GetAllTables', #DestinationSchema, CURRENT_TIMESTAMP, 'ERROR: ' + ERROR_MESSAGE(), 0
END CATCH
--Return value:
SELECT 1;
END
END
You seem to be missing some quotation marks when building your dynamic SQL
Try this
SELECT #SQL = N'IF NOT EXISTS (SELECT * FROM [' + #SourceDatabase + '].SYS.SCHEMAS WHERE NAME = [' + #DestinationSchema + '])
BEGIN
SELECT #SQL = N''USE ['+ #SourceDatabase +'];
EXEC(''CREATE SCHEMA '+ #DestinationSchema +' '')''
EXEC sp_executesql #SQL
END'
Thank you #Sandip Patel for your help,
Thank you Paul Bambury for your help
It work!!!
The problem was missing quotation marks when building my dynamic SQL.
Like this:
--Create Temporary table
SELECT #SQL ='SELECT * INTO SANDBOX.dbo.TempTables FROM OPENQUERY(['+#SourceServer+'],
''
SELECT * FROM ICTNONID.information_schema.tables where TABLE_SCHEMA = '''''+#SourceSchema+'''''
'')
WHERE TABLE_NAME NOT in (SELECT IGNORENAME FROM CORE.dbo.CopyTablesProdIgnore where IGNORETYPE = ''TABLE'' AND schemaname = '''+#SourceSchema+''')
'
EXEC sp_executesql #SQL
Below store procedure gives following error
com.microsoft.sqlserver.jdbc.SQLServerException: Ambiguous column name 'Incident_id'
USE [FusionSysLive]
GO
/****** Object: StoredProcedure [dbo].[RCPT_Search_Reports] Script ****/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[RCPT_Search_Reports]
#pagesize int = 10,
#pagestart int= 0,
#querysrting varchar(20) = '',
#orderBy varchar(40)= '',
#incident_id numeric(9) =null,
#searchdate varchar(20) =null ,
#search_string varchar(40) =null ,
#action_type varchar(40) =null ,
#security_grp_id numeric(10),
#company_id numeric(10)
as
set nocount on
set quoted_identifier off
CREATE TABLE #Temp (
Row numeric(10, 0) ,
Incident_id numeric(10, 0) null,
Description varchar(50),
Creation_timestamp varchar(100) null,
)
set nocount on
set quoted_identifier off
declare #query varchar(max)
set #query = 'select ROW_NUMBER() OVER (order by '+#orderBy +') AS Row,inc.Incident_id, inc.Description, inc.Creation_timestamp from Incident inc, Incident_list incl where inc.Incident_id = incl.Incident_id '
If(#security_grp_id = 1)
Begin
Set #query = #query + 'and (inc.Company_id ='+cast(#company_id as varchar)+' or inc.Company_id is null) '
End
Else
Begin
Set #query = #query + 'and inc.Company_id ='+cast(#company_id as varchar)
End
If ( ( #incident_id<>0 and #incident_id is not null) or ( (#action_type = 'byGroupID' or #action_type = 'byGroupName' ) and #incident_id=0 and #search_string='' and #searchdate='' ))
Begin
Set #query = #query + ' and inc.Incident_id=' + cast(#incident_id as varchar)
End
If (#action_type is not null and #search_string is not null and #action_type!='' and #search_string!='' )
Begin
If (#action_type = 'byGroupID')
Begin
Set #query = #query + ' and incl.Recipient_list_id in (select Group_id from Contact_group where Group_id like '''+ #search_string + '%'') '
End
Else If (#action_type = 'byGroupName')
Begin
Set #query = #query + ' and incl.Recipient_list_id in (select Group_id from Contact_group where Group_name like '''+ #search_string + '%'') '
End
End
If (#searchdate is not null and #searchdate!='' )
Begin
Set #query = #query + ' and CONVERT(datetime, FLOOR(CONVERT(float(24), Creation_timestamp))) =''' + #searchdate + ''''
End
set #query = #query + ' order by inc.Incident_id';
print #query
insert into #Temp exec(#query)
select row ,Incident_id , Description , Creation_timestamp
from #Temp where Row > #pagestart and row <= (#pagestart + #pagesize)
select count(*) as total_count from #Temp
drop table #Temp
I have a SQL Server 2008 with a table that acts like a hash-map. basically, there's three columns (id, key, val) and I need to pull the other columns a, b, c, d, e.
The purpose is to basically choose the database I need to query data from. Similar to this issue Using the correct database
I have got the SQL using a brute force method. I'm just trying do this in a better, more efficient way
Here's the SQL I'm trying to get to work:
CREATE PROCEDURE [dbo].[me]
#partitionName VARCHAR(64),
#id INT
AS
BEGIN
SET NOCOUNT ON
SET ROWCOUNT 0
DECLARE #table as varchar(128)
DECLARE #sql as nvarchar(4000)
DECLARE #params as nvarchar(4000)
DECLARE #s_key as varchar(64)
DECLARE #paramDefinition as nvarchar(4000)
DECLARE #a INT
DECLARE #b VARCHAR(32)
DECLARE #c VARCHAR(32)
DECLARE #d VARCHAR(32)
DECLARE #e VARCHAR(32)
SET #table = #partitionName + '.dbo.hash_table'
SET #sql =
N'SELECT ' +
N' #a = MAX(CASE WHEN [key] = ''a'' THEN value ELSE '''' END),
#b = MAX(CASE WHEN [key] = ''b'' THEN value ELSE '''' END),
#c = MAX(CASE WHEN [key] = ''c'' THEN value ELSE '''' END),
#d = MAX(CASE WHEN [key] = ''d'' THEN value ELSE '''' END),
#e = MAX(CASE WHEN [key] = ''e'' THEN value ELSE '''' END)
FROM ' + #table +
N'WHERE id = ' + CONVERT(VARCHAR(3), #id)
EXEC sp_executesql #sql
But, this gives the following error
Must declare the scalar variable "#a"
I have a feeling I need to do something like pass in #paramsDefinition to sp_executesql
But so far, these have failed
SET #paramDefinition = '#a INT OUTPUT, '
+ ' #b varchar(32) OUTPUT, '
+ ' #c varchar(32) OUTPUT, '
+ ' #d varchar(32) OUTPUT,'
+ ' #r varchar(32) OUTPUT'
...
EXEC sp_executesql #sql, #paramDefintions
I get
Incorrect syntax near '='.
Here is the brute force method (which works but hits the DB 5 times)
SET #key = 'a'
SET #sql =
N' SELECT #a = val FROM ' + #table +
N' WHERE key = ' + quotename(#key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), #nid)
EXEC sp_executesql #sql, N'#a varchar(32) OUTPUT', #a = #a OUTPUT
SET #key = 'b'
SET #sql =
N' SELECT #b = val FROM ' + #table +
N' WHERE key = ' + quotename(#key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), #id)
EXEC sp_executesql #sql, N'#b varchar(32) OUTPUT', #b = #b OUTPUT
SET #key = 'c'
SET #sql =
N' SELECT #c = val FROM ' + #table +
N' WHERE key = ' + quotename(#key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), #id)
EXEC sp_executesql #sql, N'#c varchar(32) OUTPUT', #c = #c OUTPUT
SET #key = 'd'
SET #sql =
N' SELECT #d = val FROM ' + #table +
N' WHERE key = ' + quotename(#key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), #id)
EXEC sp_executesql #sql, N'#d varchar(32) OUTPUT', #d = #d OUTPUT
SET #key = 'e'
SET #sql =
N' SELECT #e = val FROM ' + #table +
N' WHERE key = ' + quotename(#key, '''') +
N' AND id = ' + CONVERT(VARCHAR(3), #id)
EXEC sp_executesql #sql, N'#e varchar(32) OUTPUT', #e = #e OUTPUT
SELECT #a as [a], #b as [b], #c as [c], #d as [d], #r as [r]
You can try to use a temporary table like this:
CREATE PROCEDURE [dbo].[me]
#partitionName VARCHAR(64),
#id INT
AS
BEGIN
SET NOCOUNT ON
SET ROWCOUNT 0
DECLARE #table as varchar(128)
DECLARE #sql as nvarchar(4000)
DECLARE #params as nvarchar(4000)
DECLARE #s_key as varchar(64)
DECLARE #paramDefinition as nvarchar(4000)
DECLARE #a INT
DECLARE #b VARCHAR(32)
DECLARE #c VARCHAR(32)
DECLARE #d VARCHAR(32)
DECLARE #e VARCHAR(32)
SET #table = #partitionName + '.dbo.hash_table'
CREATE TABLE #tmp (code varchar(50))
SET #sql =
N'SELECT ' +
N' MAX(CASE WHEN [key] = ''a'' THEN value ELSE '''' END) as [a],
MAX(CASE WHEN [key] = ''b'' THEN value ELSE '''' END) as [b],
MAX(CASE WHEN [key] = ''c'' THEN value ELSE '''' END) as [c],
MAX(CASE WHEN [key] = ''d'' THEN value ELSE '''' END) as [d],
MAX(CASE WHEN [key] = ''e'' THEN value ELSE '''' END) as [e]
FROM ' + #table +
N'WHERE id = ' + CONVERT(VARCHAR(3), #id)
INSERT INTO #tmp (code)
EXEC sp_executesql #sql
SELECT * from #tmp
Hope it helps.
Try this.....
Dynamic SQL has its own scope, Variables in your stored procedure arent visible to to your dynamic sql, you will need to declare these variables as second parameter to sp_execuetsql and since you are reverting values back in these variables, you will need to use key word OUTPUT with these variables when passing them to sp_executesql , as follows
CREATE PROCEDURE [dbo].[me]
#partitionName SYSNAME,
#id INT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #table as varchar(128)
DECLARE #sql as nvarchar(4000)
DECLARE #params as nvarchar(4000)
DECLARE #s_key as varchar(64)
DECLARE #paramDefinition as nvarchar(4000)
DECLARE #a INT
DECLARE #b VARCHAR(32)
DECLARE #c VARCHAR(32)
DECLARE #d VARCHAR(32)
DECLARE #e VARCHAR(32)
SET #table = #partitionName + 'hash_table'
SET #sql = N'SELECT ' +
N' #a = MAX(CASE WHEN [key] = ''a'' THEN value ELSE '''' END),
#b = MAX(CASE WHEN [key] = ''b'' THEN value ELSE '''' END),
#c = MAX(CASE WHEN [key] = ''c'' THEN value ELSE '''' END),
#d = MAX(CASE WHEN [key] = ''d'' THEN value ELSE '''' END),
#e = MAX(CASE WHEN [key] = ''e'' THEN value ELSE '''' END)
FROM dbo.' + QUOTENAME(#table) +
N' WHERE id = #id)'
EXEC sp_executesql #sql
,N'#a INT OUTPUT, #b VARCHAR(32) OUTPUT,#b VARCHAR(32) OUTPUT,#c VARCHAR(32) OUTPUT,
#d VARCHAR(32) OUTPUT,#e VARCHAR(32) OUTPUT, #id INT'
,#a OUTPUT
,#b OUTPUT
,#c OUTPUT
,#d OUTPUT
,#e OUTPUT
,#id
END