Using COALESCE in Sql server - sql

I have a stored procedure which will update the album details if a album id is present in the table , if not it will add a new record.
User some times can update all values, or some times leaves some values. So in case if the user leave the values for updating old data should be kept in table.
For this i found solution to make use of coasesce in sql...
I wrote my SP as:
UPDATE [dbo].[tbl_M_Album]
SET [AlbumName] = #AlbumName
,[ImageName] = #Imagename
,[Description] = coalesce(#Description,[Description])
,[Imagepath] = #Imagepath
,[UpdatedBy] = #CreatedBy
,[UpdatedDate] = #CreatedDate
where AlbumID =#AlbumId
end
If i did not send the Description the old data is not keeping, it is overriding by empty data.
Please some one help me if i have any mistakes..

The value of #Description you pass is blank or empty, not NULL.
COALESCE and other null checking functions treat '' as a non null value.
These are all true,
NULL IS NULL
'' IS NOT NULL
' ' IS NOT NULL
If you want to check for NULL, '' (empty) or ' ' (whitespace), you could use
COALESCE(LEN(TRIM(#Description)), 0) = 0
or, for just NULL and empty,
COALESCE(LEN(#Description), 0) = 0
but, it would be more efficient to avoid passing empty or blank values.
You could rewrite your SP like this
IF COALESCE(LEN(TRIM(#Description)), 0) = 0
UPDATE [dbo].[tbl_M_Album]
SET
[AlbumName] = #AlbumName
,[ImageName] = #Imagename
,[Imagepath] = #Imagepath
,[UpdatedBy] = #CreatedBy
,[UpdatedDate] = #CreatedDate
WHERE
[AlbumID] = #AlbumId;
ELSE
UPDATE [dbo].[tbl_M_Album]
SET
[AlbumName] = #AlbumName
,[ImageName] = #Imagename
,[Description] = #Description
,[Imagepath] = #Imagepath
,[UpdatedBy] = #CreatedBy
,[UpdatedDate] = #CreatedDate
WHERE
[AlbumID] = #AlbumID;

Check if the value assigned for #Description is an empty string or NULL. If you pass an empty string in #Description then that is the problem. Only passing NULL will "default" to the next non-null value (this applies to both COALESCE or ISNULL).
Hope this helps.

Use this query.
UPDATE [dbo].[tbl_M_Album]
SET [AlbumName] = #AlbumName
,[ImageName] = #Imagename
,[Description] = Case WHEN (#Description IS NULL OR LTRIM(RTRIM(#Description) = '')
THEN [Description]
ELSE #Description
,[Imagepath] = #Imagepath
,[UpdatedBy] = #CreatedBy
,[UpdatedDate] = #CreatedDate
where AlbumID =#AlbumId
end

Related

SQL Server Dynamic where clause query

I am trying to create a dynamic query I just to do with linq
from a in Customers
where (string.IsNullOrEmpty(name)? true : a.FirstName == name) && (string.IsNullOrEmpty(last)? true : a.LastName == last)
select a;
but now I need to do in on Stored Procedure and I don't want to concatenate for security reason and performance. The most close example I found is this query
declare #Name as varchar(100)
declare #GroupName as varchar(100)
set #Name = ''
set #GroupName = 'Manufacturing'
SELECT TOP (1000) [DepartmentID]
,[Name]
,[GroupName]
,[ModifiedDate]
FROM [AdventureWorks2017].[HumanResources].[Department]
where ([Name] = case
when #Name is null or #Name = '' then null
else #Name
end
)
and
(
[GroupName] = case
when #GroupName is null or #GroupName = '' then null
else #GroupName
end
)
This almost works. I think this should be the answer but the where clause fails for obvious reason.
I would like the where clause could produce '1=1' if the param "Name" or "GroupName" is null
example
#Name = "Somename"
#GroupName = null
where (Name = #Name) and (1 = 1)
--or
#Name = null
#GroupName = "Somegruopname"
where (1 = 1) and (GroupName = #GroupName)
--
#Name = null
#GroupName = null
where (1 = 1) and (1 = 1)
You want it to succeed if the variable is null or empty or a match, so I would just write that in your stored procedure.
WHERE (#FirstName is null OR #FirstName = '' OR [FirstName] = #FirstName)
AND (#LastName is null OR #LastName = '' OR [LastName] = #LastName)
Please try this:
declare #Name as varchar(100)
declare #GroupName as varchar(100) = 'Manufacturing'
set #Name = LTRIM(RTRIM(#Name))
set #GroupName = 'Manufacturing'
SELECT TOP (1000) [DepartmentID]
,[Name]
,[GroupName]
,[ModifiedDate]
FROM [AdventureWorks2017].[HumanResources].[Department]
where ([Name] = coalesce(#Name,'') = '' OR [Name] = #Name)
and
([GroupName] = coalesce(#GroupName, '') = '' OR [GroupName] = #GroupName)

Stored procedure update specific column by parameter

I am developing a stored procedure to update specific columns using parameters.
For example:
CREATE PROCEDURE save_proc
(
#userid varchar(5),
#column varchar(10),
#data varchar(50)
)
AS
BEGIN
UPDATE MyProfile
SET #column = #data
WHERE userid = #userid
The following is my code that I've tried but didn't work. Is it possible to do such an update by updating specific columns through parameters? Thanks
You can build up a query in your stored procedure and execute.
CREATE PROCEDURE save_proc
(
#userid varchar(5),
#column varchar(10),
#data varchar(50)
)
AS
BEGIN
exec sp_executesql N'UPDATE MyProfile SET ' + #column + '=''' + #data + ''' WHERE userid = ''' + #userid + ''''
END
The method may lead to security concern however.
Its doable but i would avoid doing it.... you code should be like below:
DECLARE #column varchar(10)
DECLARE #data varchar(50)
UPDATE DummyTable
SET
col1 = CASE WHEN #column = 'Col1' THEN #data ELSE col1 END ,
col2 = CASE WHEN #column = 'Col2' THEN #data ELSE col2 END
where userid = #userid
.
.
.
Hope that this is what you are looking for
Using a CASE statement causes all columns identified to once again be updated; this would invoke a reindexing for some indexes upon columns wherein that change, even if the same value, occurs. Waste of execution updates on server.
An IF statement is best option for single value, especially if value is NOT the same type as the column datatype.
IF(#fieldName IS NULL) SELECT #fieldName = ''
IF(#updateValue IS NULL) SELECT #updateValue = ''
DECLARE #myCount int
SELECT #myCount = count(*) FROM [dbo].[myTable] WHERE #inventoryID = #updateInventoryID
--if no valid data to update, return -1 for noUpdate
IF(0 = #updateInventoryID
OR 0 = #myCount
OR '' = #fieldName
OR '' = #updateValue)
RETURN -1
BEGIN TRAN
IF('notes' = #fieldName)
UPDATE [dbo].[myTable]
SET [notes] = #updateValue, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
IF('reorderPoint' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [reorderPoint] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('safetyStock' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [safetyStock] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('quantityOnHand' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [quantityOnHand] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('totalLeadTimeDays' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [totalLeadTimeDays] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('stockTakeETADate' = #fieldName)
BEGIN
SET #newValueDatetime = CONVERT(datetime, #updateValue)
UPDATE [dbo].[myTable]
SET [stockTakeETADate] = #newValueDatetime, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
COMMIT
A Try/Catch is advisable

How to run stored procedure query between 2 table & insert data base on reference column?

I've created a simple stored procedure to update my Sample_TAG_NUMBERTEST table but I need it to get an ItemCode from another table PartItem by using both SOLine & SONbr to do the query but I don't know how to write it.
2nd thing I need to do is when my StatusCode column is N001 then my DESC column will automatically insert NEW ORDER data value, for PR002 my DESC column will become Progress.
How can I do that? Thanks in advance.
ALTER PROCEDURE [dbo].[SampleTagNumberUpdate]
#sONbr nvarchar(50) = NULL,
#SOLine nvarchar(50) = NULL,
#SerialNbr nvarchar(50) = NULL,
#StatusCode nvarchar(50) = NULL,
#PackType nvarchar(50) = NULL,
#PalletID nvarchar(50) = NULL,
#PackingListNo nvarchar(50) = NULL,
#ItemCode nvarchar(50) = NULL,
#CrDateTime nvarchar(50) = NULL,
#CrUserID nvarchar(50) = NULL,
#return nvarchar(50) = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS(SELECT sONbr , SOLine
FROM [SampleSystem].[dbo].[Sample_TAG_NUMBERTEST]
WHERE sONbr = #sONbr AND SOLine = #SOLine)
BEGIN
UPDATE [SampleSystem].[dbo].[Sample_TAG_NUMBERTEST]
SET SerialNbr = #SerialNbr
,StatusCode = #StatusCode
,PackType = #PackType
,PalletID = #PalletID
,PackingListNo = #PackingListNo
,ItemCode = #ItemCode
,LastUpdDateTime = GETDATE()
,LastUpdUserID = #CrUserID
WHERE sONbr = #sONbr AND SOLine = #SOLine
IF ##ERROR <> 0
Set #Return = 'UPDATE FAILED'
ELSE
Set #Return = 'UPDATE SUCCESSFULLY'
END
ELSE
BEGIN
INSERT INTO [SampleSystem].[dbo].[Sample_TAG_NUMBERTEST](SONbr, SOLine, SerialNbr
,StatusCode
,PackType
,PalletID
,PackingListNo
,ItemCode
,CrDateTime
,CrUserID)
VALUES(#sONbr, #SOLine, #SerialNbr, #StatusCode, #PackType
,#PalletID
,#PackingListNo
,#ItemCode
,GETDATE()
,#CrUserID)
IF ##ERROR <> 0
Set #Return = 'INSERT DATA FAILED'
ELSE
Set #Return = 'INSERT DATA SUCCESSFULLY'
END
END
I believe I have provided an example for both questions below:
UPDATE T
SET ItemCode = (SELECT PI.ItemCode FROM PartItem AS PI WHERE PI.SO = #SO AND PI.SO_LINE = #SO_LINE),
DESC = CASE #StatusCode WHEN 'N001' THEN 'NEW ORDER'
ELSE CASE #StatusCode WHEN 'PR002' THEN 'PROGRESS' ELSE '' END
END,
<other columns here...>
FROM SAMPLE_TAG_NUMBERTEST AS T

Stored procedure filtering

Need to write a procedure to retrieve data in which some selection criteria were not taken into procedure if a user not enters a value. I am filtering :
WHERE #ts = [ts] or #username = [username]
or #ip = [ip] or #my_category = [my_category]
or #my_name = [my_name] or #nm1_name = [nm1_name]
or #param = [param] or #short_descr = [short_descr]
When I call a stored procedure and when passed one of the parameters that filtering works, and when I write some ,only one filtering work (because I have in my logic 'or'). Replaced by 'and' not satisfied unnecessarily have to pass all the parameters, and I need to transfer only those on which I want to filter out. Please help me to solve this problem
WHERE (#ts IS NULL OR [ts] = #ts)
and (#username IS NULL OR [username] = #username)
and (#ip IS NULL OR [ip] = #ip)
and (#my_category IS NULL OR [my_category] = #my_category)
and (#my_name IS NULL OR [my_name] = #my_name)
and (#nm1_name IS NULL OR [nm1_name] = #nm1_name)
and (#param IS NULL OR [param] = #param)
and (#short_descr IS NULL OR [short_descr] = #short_descr)
EDIT:
I've seen in comment to other answer that you are passing blank string instead of NULLs. In that case you need to handle them instead (or in addition) to NULLs
WHERE (#ts IS NULL OR #ts = '' OR [ts] = #ts)
and (#username IS NULL OR #username = '' OR [username] = #username)
and (#ip IS NULL OR #ip = '' OR [ip] = #ip)
and (#my_category IS NULL OR #my_category = '' OR [my_category] = #my_category)
and (#my_name IS NULL OR #my_name = '' OR [my_name] = #my_name)
and (#nm1_name IS NULL OR #nm1_name = '' OR [nm1_name] = #nm1_name)
and (#param IS NULL OR #param = '' OR [param] = #param)
and (#short_descr IS NULL OR #short_descr = '' OR [short_descr] = #short_descr)
You're setting your parameters to NULL when you're not using the related filter, right?
So you could use a query like this:
WHERE isnull(#ts, [ts]) = [ts]
and isnull(#username, [username]) = [username]
and isnull(#ip, [ip]) = [ip]
and isnull(#my_category, [my_category]) = [my_category]
and isnull(#my_name, [my_name]) = [my_name]
and isnull(#nm1_name, [nm1_name]) = [nm1_name]
and isnull(#param, [param]) = [param]
and isnull(#short_descr, [short_descr]) = [short_descr]
option (recompile)
I advocate using option (recompile) in such a scenario
EDIT:
with '' instead of NULL
WHERE #ts in ('', [ts])
and #username in ('', [username])
and #ip in ('', [ip])
and #my_category in ('', [my_category])
and #my_name in ('', [my_name])
and #nm1_name in ('', [nm1_name])
and #param in ('', [param])
and #short_descr in ('', [short_descr])
(more readable than using OR each and every time and it doesn't require recompile*)
(*) as parameters will not be sniffed anyway

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

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