Checking if every parameter of a stored procedure got default value or not - sql

How would you implement that check? You have N parameters for a stored procedure.
If all value are null or 0 or empty string, run the code else skip it
This is how I implemented it, is there a better way?
I really don't like what I did so I'm open to any better idea, must be easily maintainable since it would be done at many places
declare #doRunIt bit
declare #checkAllNull varchar(max)
declare #sumOfInt int
set #checkAllNull = ''
set #checkAllNull = #checkAllNull + coalesce(#param1,'')
set #checkAllNull = #checkAllNull + coalesce(#param2,'')
set #checkAllNull = #checkAllNull + coalesce(#param3,'')
set #checkAllNull = #checkAllNull + coalesce(#param4,'')
set #checkAllNull = #checkAllNull + coalesce(#param5,'')
set #checkAllNull = #checkAllNull + coalesce(#param6,'')
set #sumOfInt = coalesce(#param7,0)+coalesce(#param8,0)+
coalesce(#param9,0)+coalesce(#param10,0)+
coalesce(#param11,0)+coalesce(#param12,0)
set #checkAllNull = #checkAllNull + cast(#sumOfInt as varchar(max))
if ( isnumeric(#checkAllNull)=1 )
if (cast(#checkAllNull as int) > 0)
set #doRunIt = 1
else
set #doRunIt = 0
else
if (ltrim(rtrim(#checkAllNull)) <> '')
set #doRunIt = 1
else
set #doRunIt = 0
End goal is to move the check made in code for inserting empty row, if all parameters are null or using default value, in the DB into the stored procedure, so other apps can call the same stored procedure without having to deal with checking for empty row.

Your code
DECLARE #IsValid BIT = dbo.IsValidParameter(#param1) &
dbo.IsValidParameter(#param2) &
dbo.IsValidParameter(#param3) &
dbo.IsValidParameter(#param4)
Helper function
CREATE FUNCTION dbo.IsValidParameter(#p1 Sql_Variant)
RETURNS bit
AS
BEGIN
IF #p1 IS NULL OR #p1 = '' OR #p1 = 0
RETURN 0
RETURN 1
END
GO

Related

Multiple conditional Where clause

I currently have a query that will pull a bunch of information from my database based on whatever where condition that I want to use.
declare #CaseNum char(7),
#ImportId char,
#FormatId char,
#SessionId char(5)
set #CaseNum = '' --I can place the value that I want to search by in here
set #ImportId = ''
set #FormatId = ''
set #SessionId = ''
--------------------
query in here
--------------------
where
gr.[CaseNum] = #CaseNum --currently I have to comment the ones I'm not using out
--im.[ImportId] = #ImportId
--fr.[FormatId] = #FormatId
--se.[SessionId] = #SessionId
I want to be able to take the comment portion out and simply display all rows if the parameter = ''
For example if I use set #CaseNum = '1234567' then it will search by that parameter and if I use #FormatId = '12' it will search by that one.
I have tried using the following and a few other attempts but I am getting nowhere fast.
where
gr.[CaseNum] = '%' + #CaseNum + '%'
and im.[ImportId] = '%' + #ImportId + '%'
and fr.[FormatId] = '%' + #FormatId + '%'
and se.[SessionId] = '%' + #SessionId + '%'
With help from the link that #Norman posted I figured it out. I wanted to post my solution for others to see.
declare #CaseNum varchar(MAX),
#ImportId varchar(MAX)
set #CaseNum = ''
set #ImportId = ''
----------------------------------------------------------------------------
If(#CaseNum = '') --Sets the parameter to NULL for COALESCE to work
Begin
Select #CaseNum = NULL
End
If(#ImportId = '') --Sets the parameter to NULL for COALESCE to work
Begin
Select #ImportId = NULL
End
--------------------
query in here
--------------------
where
gr.[CaseNum] = COALESCE(#CaseNum, gr.[CaseNum])
and im.ImportId = COALESCE(#ImportId, im.ImportId)
This solution allows the query to use just a single parameter or all at the same time.
You might want to look into building your query.
DECLARE #Number varchar(10)
DECLARE #Where varchar(max)
DECLARE #Query varchar(max)
SET #Query = 'SELECT * FROM TestTable'
SET #Where = ''
SET #Number = '3'
IF ISNULL(#Number, '') != ''
BEGIN
SET #Where = #Where + 'and testNumber = ' + #Number
END
IF LEN(#Where) > 0
BEGIN
SET #Where = SUBSTRING(#Where, 4, LEN(#Where))
END
if ISNULL(#Where, '') != ''
BEGIN
SET #Query = #Query + ' WHERE ' + #Where
END
EXEC(#Query)
Check out this gentleman's article for reference: https://social.msdn.microsoft.com/forums/sqlserver/en-US/1ec6ddd9-754b-4d78-8d3a-2b4da90e85dc/dynamically-building-where-clauses

SQL Server: how to declare and set variable in dynamic procedure

I would like to declare and set a variable as part of a dynamic procedure.
I am new to this so the following is just to indicate what I am trying to achieve.
Can someone show me how to write this correctly (just regarding these lines) ?
#searchMain nvarchar(100) = '',
#searchInput nvarchar(256) = ''
AS
BEGIN
SET NOCOUNT ON;
BEGIN
DECLARE #sql nvarchar(max),
#searchDate datetime
CASE WHEN #searchMain = 'col1' THEN SET #searchDate = #searchInput ELSE SET #searchDate = '' END
SET #sql = 'SELECT TOP 100
-- ...
Many thanks in advance for any help with this, Mike.
Change this:
CASE WHEN #searchMain = 'col1' THEN SET #searchDate = #searchInput ELSE SET #searchDate = '' END
To this:
SET #searchDate = CASE WHEN #searchMain = 'col1' THEN #searchInput ELSE '' END

Invalid length parameter passed to the LEFT or SUBSTRING function

Following is my query and it works fine when I have like TRAILER_MAKE_MODEL 'testing ~ testing, test ~ testq,' ends with comma but can't handle 'testing ~ testing, test ~ testq' same as for other variable TRAILER_IDV. I tried my best but cant work it out any help would be appreciated.
My aim is to get the comma separated value for xml.
DECLARE #TRAILER_MAKE_MODEL VARCHAR(MAX)
DECLARE #TRAILER_IDV VARCHAR(MAX)
DECLARE #USER_TYPE VARCHAR(MAX)
DECLARE #START_INDEX_1 INT
DECLARE #START_INDEX_4 INT
DECLARE #END_INDEX_1 INT
DECLARE #END_INDEX_4 INT
DECLARE #VALUE VARCHAR(50)
DECLARE #QUERY VARCHAR(MAX)
set #TRAILER_MAKE_MODEL='testing ~ testing, test ~ testq,'
set #TRAILER_IDV='3500, 3400,'
set #USER_TYPE='MOBILE'
set #QUERY = ''
set #START_INDEX_1 = 1
set #START_INDEX_4 = 1
set #END_INDEX_1 = 0
if ISNULL(#TRAILER_MAKE_MODEL,'') <> ''
begin
WHILE #START_INDEX_1 > 0 and #START_INDEX_1 < len(#TRAILER_MAKE_MODEL)
BEGIN
SET #END_INDEX_1 = CHARINDEX(',',#TRAILER_MAKE_MODEL,#START_INDEX_1)
if #END_INDEX_1 = 0 and #START_INDEX_1 = 1
Begin
SET #END_INDEX_1 = len(#TRAILER_MAKE_MODEL)
END
if #USER_TYPE <> 'MOBILE'
Begin
SET #END_INDEX_1 = #END_INDEX_1 +1
End
SET #VALUE = SUBSTRING(#TRAILER_MAKE_MODEL,#START_INDEX_1,#END_INDEX_1 - #START_INDEX_1)
SET #QUERY = #QUERY + 'UNION ALL SELECT ''' + #VALUE + ''' TRAILER_MAKE_MODEL'
SET #END_INDEX_4 = CHARINDEX(',',#TRAILER_IDV,#START_INDEX_4)
if #END_INDEX_4 = 0 and #START_INDEX_4 = 1
Begin
SET #END_INDEX_4 = len(#TRAILER_IDV)
END
if #USER_TYPE <> 'MOBILE'
Begin
SET #END_INDEX_4 = #END_INDEX_4 +1
End
SET #VALUE = SUBSTRING(#TRAILER_IDV,#START_INDEX_4,#END_INDEX_4 - #START_INDEX_4)
SET #QUERY = #QUERY + ',' + #VALUE + 'TRAILER_IDV '
print #QUERY
SET #START_INDEX_1 = #END_INDEX_1 + 1
SET #START_INDEX_4 = #END_INDEX_4 + 1
END
select #QUERY=substring(#QUERY, 10, LEN(#QUERY) - 9)
EXEC (#QUERY)
END
You already have a lot of code here so two extra lines where you assign a comma at the end of each string should probably not slow things down for you or make the code less maintainable.
SET #TRAILER_MAKE_MODEL += ',';
SET #TRAILER_IDV += ',';
I don't really understand what your code does but to get the result you are getting you can use a split string function that returns the index of the item like this.
select T1.Item as TRAILER_MAKE_MODEL,
T2.Item as TRAILER_IDV
from dbo.SplitString(#TRAILER_MAKE_MODEL, ',') as T1
inner join dbo.SplitString(#TRAILER_IDV, ',') as T2
on T1.ItemNumber = T2.ItemNumber

how to write query for optional parameters

hello friends i am following 3 layer architecture for my project i mean
presentation layer, business logic layer and finally database layer
my question is that i am making a search feature for my project where i need to send parameter through a method for search query which is to make on business logic layer
i am to send parameter from presentation layer by calling some method and those parameter will be used on business logic layer's method to make appropriate query
it's not sure sure how many parameters will be send every time i mean parameters are optional
so my question is that how should i send these optional parameter for getting exactly the require parameter on business logic layer.
What is the best way, i am programming in asp.net
If you use business entities, mark every properties by custom attribute with (mask = 1, 2, 4, 8..., required = true/false).
class Product
{
[FieldAttribute(Required=true, Mask= 0)]
public int Id {get; set;}
...
[FieldAttribute(Required=false, Mask=1)]
public string ProductName { get; set;}
}
then you can use reflection to read all required properties and pass them to sp. if some not required parameters is null (use Nullable<>) don't increment mask (mask &= propertyMask).
Use integer mask to partial update.
/*
exec dbo.Update_Product #product_id = 1, #quantity = 3, #mask = 0x0004
exec dbo.Update_Product #product_id = 1, #product_name = 'new name', #comment = 'new comment', #mask = 0x0003
*/
alter proc dbo.Update_Product
#product_id int
,#product_name nvarchar(100) = NULL -- 0x0001
,#comment nvarchar(255) = NULL -- 0x0002
,#quantity int = NULL -- 0x0004
,#mask int
AS
update dbo.Product
SET
ProductName = CASE WHEN (#mask & 0x0001) > 0 THEN #product_name ELSE ProductName END
,Comment = CASE WHEN (#mask & 0x0002) > 0 THEN #comment ELSE Comment END
,Quantity = CASE WHEN (#mask & 0x0004) > 0 THEN #quantity ELSE Quantity END
WHERE id = #product_id
2) For select, use two masks (select, and where)
/*
exec dbo.Select_Product #select_mask = 0x0001, #where_mask = 0
exec dbo.Select_Product #select_mask = 0x0003, #where_mask = 0
exec dbo.Select_Product #select_mask = 0x0003, #where_mask = 0x0004, #quantity = 2
*/
alter proc dbo.Select_Product
#select_mask int
,#where_mask int
,#product_name nvarchar(100) = NULL -- 0x0001
,#comment nvarchar(255) = NULL -- 0x0002
,#quantity int = NULL -- 0x0004
as
DECLARE #select varchar(max)
DECLARE #where varchar(max)
SET #select = 'select Id '
IF (#select_mask & 0x0001) > 0
SET #select = #select + ',ProductName'
IF (#select_mask & 0x0002) > 0
SET #select = #select + ',Comment'
IF (#select_mask & 0x0004) > 0
SET #select = #select + ',Quantity'
SET #select = #select + ' from dbo.Product'
IF #where_mask > 0
SET #where = ' where ' + CASE WHEN (#where_mask & 0x0001) > 0 THEN 'ProductName = ''' + #product_name + '''' ELSE '' END
+ CASE WHEN (#where_mask & 0x0002) > 0 THEN 'Comment = ''' + #comment + '''' ELSE '' END
+ CASE WHEN (#where_mask & 0x0004) > 0 THEN 'Quantity = ' + CONVERT(varchar(10), #quantity) ELSE '' END
PRINT #select + #where
exec (#select + #where)

Parameterizing Dynamic SQL issue with SQL_VARIANT datatype

I've been refactoring a huge dynamic SQL statement, and think I may have hit a roadblock. The goal has been to parameterize it. I'm using SQL Server 2005.
I have an int variable (#i) that determines what column I need to update. Here's what I've been doing:
if #i = 1
begin
set #updateClause = 'Column1 = #newValue';
set #updateClauseDataType = 'varchar(10)';
set #updateValue = #foo;
end
else if #i = 2
begin
set #updateClause = 'Column2 = #newValue';
set #updateClauseDataType = 'int';
set #updateValue = #bar;
end
else if ...
Then, I try to execute my statement:
set #statement = N'update ' + #server_name + '.' + #database_name + '.dbo.Table1
set ' + #updateClause + ' where pk = #pk';
set #parameters = '#newValue ' + #updateClauseDataType + ',
#pk uniqueidentifier';
execute sp_executesql #statement,
#parameters,
#newValue = #newValue,
#pk= #pk;
This results in:
Implicit conversion from data type
sql_variant to varchar is not allowed.
Use the CONVERT function to run this
query.
I can get around this if I can somehow cast #updateValue into the correct type, which I have stored as text in #updateClauseDataType. Is there any way I can do this without having a huge if statement that interrogates the value of #updateClauseDataType?
On rereading, since you already know the data type, why not include it in the update clause?
set #updateClause = 'Column1 = cast(#newValue as varchar(10))';
set #updateClauseDataType = 'varchar(10)';
Or to avoid typing the data type twice:
set #updateClauseDataType = 'varchar(10)';
set #updateClause = 'Column1 = cast(#newValue as ' +
#updateClauseDataType + ')';