I have this stored procedure
USE [all_things]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_getThingsByType]
#thingid int,
#typeid int
AS
DECLARE #Sql NVARCHAR(MAX) = 'SELECT * from items'
IF #thingid IS NOT NULL
BEGIN
SET #Sql += ' where thingid = #thingid'
END
IF #typeid IS NOT NULL
BEGIN
SET #Sql += ' and TypeID = #typeid'
END
EXEC sp_executesql #sql, N'#thingid int,#typeid int',#thingid=#thingid,#typeid=#typeid;
Test cases:
When I run it with the thingid is null and typeid is null, I get all results which is perfect.
When the thingid is supplied and the typeid is null, the results are ok
Here is where, the results are not good: thingid is null and typeid is supplied. Everything is being returned.
What am I missing?
Thanks
Thanks to #tschmit007, I fixed it.
USE [all_things]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_getThingsByType]
#thingid int,
#typeid int
AS
DECLARE #Sql NVARCHAR(MAX) = 'SELECT * from items'
IF #thingid IS NOT NULL
BEGIN
SET #Sql += ' where thingid = #thingid'
END
IF #typeid IS NOT NULL AND #thingid IS NOT NULL
BEGIN
SET #Sql += ' and TypeID = #typeid'
END
IF #typeid IS NOT NULL AND #thingid IS NULL
BEGIN
SET #Sql += ' where TypeID = #typeid'
END
EXEC sp_executesql #sql, N'#thingid int,#typeid int',#thingid=#thingid,#typeid=#typeid;
Related
I wanna create a stored procedure to check if a sequence is with a given name is exist or no to create it or alter its value to max(Id) selected from given table name, So I create the below procedure but it throws a syntax error.
CREATE PROCEDURE EBPP_CORE.CREATE_OR_ALTER_SEQUENCE
#sequence_name VARCHAR2,
#table_name VARCHAR2
AS
BEGIN
DECLARE #MAX_ID_VAL NUMBER;
DECLARE #sequence_exist NUMBER;
SELECT #MAX_ID_VAL = CAST(ISNULL(MAX(id) + 1, 1) as nvarchar(10)) FROM #table_name ;
SELECT #sequence_exist = COUNT(*) FROM sys.sequences WHERE name = #sequence_name;
IF #sequence_exist>0
' ALTER SEQUENCE #sequence_name RESTART WITH #MAX_ID_VAL';
ELSE
'CREATE SEQUENCE #sequence_name START WITH #MAX_ID_VAL INCREMENT BY 1' ;
END
You have to use dynamic SQL to both find the current max ID and to create or alter the SEQUENCE objects. Something like this:
CREATE OR ALTER PROCEDURE EBPP_CORE.CREATE_OR_ALTER_SEQUENCE
#sequence_name nvarchar(128),
#table_name nvarchar(128)
AS
/*
drop table if exists foo
go
create table foo(id int)
exec EBPP_CORE.CREATE_OR_ALTER_SEQUENCE 'foo_seq','foo'
insert into foo(id) values (3)
exec EBPP_CORE.CREATE_OR_ALTER_SEQUENCE 'foo_seq','foo'
*/
BEGIN
DECLARE #MAX_ID_VAL bigint;
DECLARE #sequence_exist bigint;
declare #sql nvarchar(max) = concat('select #MAX_ID_VAL = MAX(id) + 1 FROM ', quotename(#table_name));
print #sql;
exec sp_executesql #sql, N'#MAX_ID_VAL bigint output', #MAX_ID_VAL=#MAX_ID_VAL output;
set #MAX_ID_VAL = coalesce(#MAX_ID_VAL,1)
SELECT #sequence_exist = COUNT(*) FROM sys.sequences WHERE name = #sequence_name;
IF #sequence_exist>0
BEGIN
set #sql = concat('ALTER SEQUENCE ', quotename(#sequence_name), ' RESTART WITH ', #MAX_ID_VAL) ;
print #sql;
exec (#sql);
END
ELSE
BEGIN
set #sql = concat('CREATE SEQUENCE ', quotename(#sequence_name), ' START WITH ', #MAX_ID_VAL,' INCREMENT BY 1') ;
print #sql;
exec (#sql);
END
END
Recently I have had to change a query from the following (fully working):
/****** WORKING ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [operations].[ROIWarehouseDatas]
(#Operation VARCHAR(50) = NULL,
#TableName NVARCHAR(255) = NULL,
#Results [dbo].[ForeSightData] READONLY)
AS
BEGIN
DECLARE #err INT
SET #err = 0
IF (#Operation = 'Insert')
BEGIN
DECLARE #SQLString NVARCHAR(4000)
DECLARE #ParamDefinition NVARCHAR(4000)
SET #SQLString = N'TRUNCATE TABLE ['+ #TableName + N'];
INSERT INTO ['+ #TableName + N']
SELECT [ID], [BrandName], [AdvertName], [VersionName], [WCPM]
FROM #Results;';
SET #ParamDefinition = N'#Operation VARCHAR(50), #Results [dbo].[ForeSightData] READONLY';
EXECUTE sp_executesql #SQLString, #ParamDefinition, #TableName, #Results
END
--ENDIF Insert
SET #err = ##ERROR
RETURN #err
END
To the following (not working):
/****** NOT WORKING ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [operations].[ROIWarehouseDatas]
(#Operation VARCHAR(50) = NULL,
#TableName NVARCHAR(255) = NULL,
#Results [dbo].[ForeSightData] READONLY)
AS
BEGIN
DECLARE #err INT
DECLARE #SQLString NVARCHAR(4000)
DECLARE #ParamDefinition NVARCHAR(4000)
SET #err = 0
IF (#Operation = 'Insert')
BEGIN
SET #SQLString = N'MERGE INTO ['+ #TableName +'] AS T
USING #Results AS S ON T.ID = S.ID
WHEN MATCHED
THEN UPDATE
SET T.[BrandName] = S.[BrandName],
T.[AdvertName] = S.[AdvertName],
T.[VersionName] = S.[VersionName],
T.[VersionDuration] = S.[VersionDuration],
T.[WCPM] = S.[WCPM]
WHEN NOT MATCHED BY TARGET
THEN INSERT ([ID], [BrandName], [AdvertName], [VersionName], [WCPM])
VALUES (S.[ID], S.[BrandName], S.[AdvertName], S.[VersionName], S.[WCPM]);';
SET #ParamDefinition = N'#Operation VARCHAR(50), #Results [dbo].[ForeSightData] READONLY';
EXECUTE sp_executesql #SQLString, #ParamDefinition, #TableName, #Results
END
--ENDIF Insert
SET #err = ##ERROR
RETURN #err
END
However, when I run the program I get the following error:
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. Unclosed quotation mark after the character string ''.
Incorrect syntax near ''.
I tried checking the syntax - and that came up as fine.
Seems not correct syntax for SQL MERGE.
WHEN NOT MATCHED BY T THEN should be Target not T:
WHEN NOT MATCHED BY Target
THEN .....
I'm trying to write a Dynamic SQL query that will allow the end-user to opt-out of entering certain search criteria. In this example, I would like the end-user to be able to enter a value for #GLAccountStart without entering a value for #GLAccountEnd and have the "IF ..." statement where #GLAccountStart IS NOT NULL and #GLAccountEnd IS NULL execute correctly.
When I try to run this in SSRS, however, entering just the first value returns 0 rows (it should return 2), and entering values for both variables actually returns the correct number of rows. Additionally, if I remove the #GLAccountEnd variable from my script entirely and just run it with the option to include #GLAccountStart, SSRS returns the correct number of rows with the proper input.
Is there a trick or something to implementing this?
USE [DataWarehouse]
GO
/****** Object: StoredProcedure [dbo].[BrowseCODA] Script Date: 6/27/2016 8:37:37 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[BrowseCODA]
#GLAccountStart int,
#GLAccountEnd int
AS
SET NOCOUNT ON;
DECLARE #SQLQuery AS nvarchar(4000)
DECLARE #ParameterDef AS nvarchar(2000)
SET #SQLQuery = 'SELECT *
FROM [DataWarehouse].[dbo].[VDocDetails]
WHERE Company+''-''+FullDocNumber IN
(SELECT Company+''-''+FullDocNumber
FROM [DataWarehouse].[dbo].[VDocDetails]
WHERE (1=1)'
IF (#GLAccountStart IS NOT NULL) AND (#GLAccountEnd IS NOT NULL)
SET #SQLQuery = #SQLQuery + ' AND (GLAccount >= #GLAccountStart) AND (GLAccount <= #GLAccountEnd)'
IF (#GLAccountStart IS NOT NULL) AND (#GLAccountEnd IS NULL)
SET #SQLQuery = #SQLQuery + ' AND (GLAccount = #GLAccountStart)'
SET #SQLQuery = #SQLQuery + ')'
SET #ParameterDef =
'#GLAccountStart int,
#GLAccountEnd int'
EXECUTE sp_Executesql #SQLQuery,
#ParameterDef,
#GLAccountStart,
#GLAccountEnd
IF ##ERROR <> 0 GOTO ErrorHandler
SET NOCOUNT OFF
RETURN(0)
ErrorHandler:
Return(##ERROR)
GO
I guess #GLAccountEnd is not getting a null value from SSRS.
But, Why don't you try simple SQL?
SELECT *
FROM [DataWarehouse].[dbo].[VDocDetails]
where GLAccount between #GLAccountStart
AND case #GLAccountEnd
when '' then #GLAccountStart
else #GLAccountEnd end
or dynamic:
USE [DataWarehouse]
GO
/****** Object: StoredProcedure [dbo].[BrowseCODA] Script Date: 6/27/2016 8:37:37 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[BrowseCODA]
#GLAccountStart varchar,
#GLAccountEnd varchar
AS
SET NOCOUNT ON;
DECLARE #SQLQuery AS nvarchar(4000)
DECLARE #ParameterDef AS nvarchar(2000)
SET #SQLQuery = 'SELECT *
FROM [DataWarehouse].[dbo].[VDocDetails]
WHERE (1=1)'
IF (#GLAccountStart <> '') AND (#GLAccountEnd <> '')
SET #SQLQuery = #SQLQuery + ' AND (GLAccount >= #GLAccountStart) AND (GLAccount <= #GLAccountEnd)'
IF (#GLAccountStart <> '') AND (#GLAccountEnd = '')
SET #SQLQuery = #SQLQuery + ' AND (GLAccount = #GLAccountStart)'
SET #ParameterDef =
'#GLAccountStart int,
#GLAccountEnd int'
EXECUTE sp_Executesql #SQLQuery,
#ParameterDef,
#GLAccountStart,
#GLAccountEnd
IF ##ERROR <> 0 GOTO ErrorHandler
SET NOCOUNT OFF
RETURN(0)
ErrorHandler:
Return(##ERROR)
GO
SSRS apparently takes the lack of input in the parameters to mean '' instead of NULL. When I changed the dynamic query to check against whether or not the values were equal to '', the code worked as-intended.
I want to pass table name as parameter and I want to that parameter in where clause
CREATE PROC [dbo].[bb_GetPrepositionInfo]
#userid INT,#propId INT,#tabName varchar(50)
AS
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
SELECT *
FROM #tblname
WHERE ([acq_id] = #propId AND [user_id] = #userid)
COMMIT
GO
Not tested but You need to use Dynamic SQL.
CREATE PROC [dbo].[bb_GetPrepositionInfo]
#userid INT,#propId INT,#tabName varchar(50)
AS
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
DECLARE #SQL varchar(250)
SELECT #SQL = 'SELECT * FROM ' + QuoteName(#tabName) + ' where acq_id=' + Quotename(#propId) + ' AND user_id=' + Quotename(#userid)
EXEC (#SQL)
COMMIT
GO
CREATE PROC [dbo].[bb_GetPrepositionInfo]
DECLARE #userid INT
DECLARE #propId INT
DECLARE #tabName varchar(50)
DECLARE #sqlCommand varchar(200)
AS
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
SET #sqlCommand = 'SELECT * from ' + #tabName +'WHERE [acq_id]='+ #propId +'AND [user_id] = '+ #userid
EXEC (#sqlCommand)
COMMIT
GO
DECLARE #dbName nvarchar(128) = 'myDb'
DECLARE #siteId int
exec ('SELECT TOP 1 #siteId = Id FROM ' + #dbName + '..myTbl')
select #siteId
When I run the script above I get the following error
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "#siteId".
(1 row(s) affected)
Why and how to fix it?
Thank you
You can use output parameters with sp_executesql.
DECLARE #dbName nvarchar(128) = 'myDb'
DECLARE #siteId int
DECLARE #SQL nvarchar(max) = N'SELECT TOP 1 #outputFromExec = Id FROM ' + quotename(#dbName) + N'..myTbl'
exec sp_executesql #SQL, N'#outputFromExec int out', #siteId out
select #siteId
The dynamic SQL is a different scope to the outer, calling SQL: so #siteid is not recognised
You'll have to use a temp table/table variable outside of the dynamic SQL:
DECLARE #dbName nvarchar(128) = 'myDb'
DECLARE #siteId TABLE (siteid int)
INSERT #siteId
exec ('SELECT TOP 1 Id FROM ' + #dbName + '..myTbl')
select * FROM #siteId
Note: TOP without an ORDER BY is meaningless. There is no natural, implied or intrinsic ordering to a table. Any order is only guaranteed by the outermost ORDER BY
You can try like below
DECLARE #sqlCommand NVARCHAR(4000)
DECLARE #ID INT
DECLARE #Name NVARCHAR(100)
SET #ID = 4
SET #sqlCommand = 'SELECT #Name = [Name]
FROM [AdventureWorks2014].[HumanResources].[Department]
WHERE DepartmentID = #ID'
EXEC sp_executesql #sqlCommand, N'#ID INT, #Name NVARCHAR(100) OUTPUT',
#ID = #ID, #Name = #Name OUTPUT
SELECT #Name ReturnedName
Source : blog.sqlauthority.com
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Andrew Foster
-- Create date: 28 Mar 2013
-- Description: Allows the dynamic pull of any column value up to 255 chars from regUsers table
-- =============================================
ALTER PROCEDURE dbo.PullTableColumn
(
#columnName varchar(255),
#id int
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #columnVal TABLE (columnVal nvarchar(255));
DECLARE #sql nvarchar(max);
SET #sql = 'SELECT ' + #columnName + ' FROM regUsers WHERE id=' + CAST(#id AS varchar(10));
INSERT #columnVal EXEC sp_executesql #sql;
SELECT * FROM #columnVal;
END
GO
A slight change in the execute query will solve the problem:
DECLARE #dbName nvarchar(128) = 'myDb'
DECLARE #siteId int
exec ('SELECT TOP 1 **''#siteId''** = Id FROM ' + #dbName + '..myTbl')
select #siteId