How can I not send Null to database while using Update - sql

If i need to just update one column do i have to give other column previous value or i can just give give the column i need to change and not null values to update in database .. here is procedure code what can i do to this procedure so that i can just need to insert the value i want to update ...
ALTER procedure [dbo].[Customer_update]
( #Id int,
#Firstname nvarchar(40)=,
#Lastname nvarchar(40)=,
#City nvarchar(40)=null,
#Country nvarchar(40)=null,
#Phone nvarchar(20)=null
)
as
begin
update Customer set FirstName=#Firstname,LastName=#Lastname,City=#City,Country=#Country,Phone=#Phone where Id=#Id
end

You almost have it and as Alex K pointed out in the comment above, the most elegant way to handle optional updates is to allow null parameters and update what is sent over.
ALTER PROCEDURE [dbo].[Customer_update]
(#Id INT,
#Firstname NVARCHAR(40) = NULL,
#Lastname NVARCHAR(40) = NULL,
#City NVARCHAR(40) = NULL,
#Country NVARCHAR(40) = NULL,
#Phone NVARCHAR(20) = NULL)
AS
BEGIN
UPDATE Customer
SET FirstName = ISNULL(#Firstname, FirstName)...
WHERE Id = #Id
END
In order to use this in client code with nullable fields, simply omit the parameter altogether or let nulls pass through (one caveat to this is when you really need to set the field to null in which case the field should probably not be nullable. Then you can implicitly send a null over and the field will be set to the proper value)
Nullable fields allow you to omit parameters from a stored procedure call and still perform the operation. This is useful when you need make changes and do not want to impact existing applications, as long as the nullable fields are not required.
Are you asking about Insert/Update in one operation?
Some people do "upserts". I personally do not like having one operation for insert/updates. I feel the client should already know what operation should be performed, also, having one update and one insert procedure makes the procedures more transparent and easier to auto generate.
However, if that is what you were asking then you would create a procedure similar to the one below:
ALTER PROCEDURE [dbo].[Customer_update]
(#Id INT = NULL,
#Firstname NVARCHAR(40) = NULL,
#Lastname NVARCHAR(40) = NULL
#City NVARCHAR(40) = NULL
#Country NVARCHAR(40) = NULL
#Phone NVARCHAR(20) = NULL)
AS
BEGIN
IF (#Id IS NULL)
BEGIN
INSERT INTO Customer...
SET #ID = ##SCOPE_IDENTITY
END
ELSE BEGIN
UPDATE Customer
SET FirtName = ISNULL(#FirstName, FirstName)
WHERE Id = #Id
END
SELECT *
FROM Customer
WHERE Id = #Id
END

You would need to use ISNULL on each column:
ALTER procedure [dbo].[Customer_update]
( #Id int,
#Firstname nvarchar(40)=,
#Lastname nvarchar(40)=,
#City nvarchar(40)=null,
#Country nvarchar(40)=null,
#Phone nvarchar(20)=null
)
as
begin
update Customer
set FirstName=ISNULL(#Firstname,FirstName),
LastName=ISNULL(#Lastname,LastName),
City=ISNULL(#City,City),
Country=ISNULL(#Country,Country),
Phone=ISNULL(#Phone,Phone)
where Id=#Id
end

Related

What's better to optimize a database: use a bunch of stored procedures with different filters or use a single one with if conditions?

I'm trying to optimize my database so, I decided to change a stored procedure which has a lot of "IF CONDITIONS" to filter with different parameters.
So, I was thinking on change it and make a bunch of stored procedures with different filters and stop using the one with a lot of "IF CONDITIONS"
And just validate on my backend which stored procedure use, instead of do it in SQL Server.
This is the best way to do it or there are better ways to do this?
Example of my actual stored procedure:
CREATE PROCEDURE [dbo].[sp_GetFilters]
#Id INT,
#Name VARCHAR(50),
#LastName VARCHAR(50),
#Age INT,
#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
IF #ID IS NOT NULL AND
#NAME IS NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE
WHERE ID = #ID
END
ELSE IF #ID IS NULL AND
#NAME IS NOT NULL AND
#LASTNAME IS NULL AND
#AGE IS NULL AND
#AND_MORE_PARAMETERS IS NULL
BEGIN
SELECT *
FROM EXAMPLE_TABLE WHERE
NAME = #NAME
END
...
and so on..
I want to change that one to a bunch of different stored procedures, each one of them with a unique filter
It is a good idea? There are better ways to optimize this stored procedure?
Thanks, for the help!
You could try one query, with parameter evaluation in the WHERE clause. I've used this approach widely with great success.
CREATE PROCEDURE dbo.sp_GetFilters
#Id INT = NULL
,#Name VARCHAR(50) = NULL
,#LastName VARCHAR(50) = NULL
,#Age INT = NULL
,#AND_MORE_PARAMETERS VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM EXAMPLE_TABLE
WHERE 1 = 1
AND CASE WHEN #Id IS NULL THEN 1 ELSE ID END = CASE WHEN #Id IS NULL THEN 1 ELSE #Id END
AND CASE WHEN #Name IS NULL THEN '1' ELSE NAME END = CASE WHEN #Name IS NULL THEN '1' ELSE #Name END
AND CASE WHEN #Age IS NULL THEN 1 ELSE AGE END = CASE WHEN #Age IS NULL THEN 1 ELSE #Age END;
/* and so on....*/
END;

Can I reuse SQL or use some type of dynamic join for this stored procedure?

I have a GetUsers stored procedure as shown below. If a #GroupId or #GroupName parameter is provided, then I need to beef up the stored procedure to ensure that only users belonging to a matching group are returned.
I've created a special table variable named #GroupUserMatches which contains a UserId/GroupId association for matching user groups. I could essentially copy/paste the SQL from the ELSE block into the IF block and update it a bit to accommodate a join to #GroupUserMatches, but I was wondering if there is a more elegant way to do this?
One concern is that I'd like to avoid having to make updates to the same SQL select in 2 different blocks in the same stored procedure. If no #GroupId or #GroupName are provided, then the user list returned should be completely unfiltered by group.
ALTER PROCEDURE [dbo].[GetUsers]
#DomainId uniqueidentifier = NULL,
#DomainName varchar(100) = NULL,
#NetworkUserId varchar(100) = NULL,
#UserPrincipalName varchar(100) = NULL,
#FirstName varchar(100) = NULL,
#LastName varchar(100) = NULL,
#EmailAddress varchar(255) = NULL,
#GroupId uniqueidentifier = NULL,
#GroupName varchar(500) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE #GroupUserMatches TABLE
(
GroupId UNIQUEIDENTIFIER,
UserId UNIQUEIDENTIFIER
)
IF(#GroupId IS NOT NULL OR #GroupName IS NOT NULL)
BEGIN
INSERT INTO #GroupUserMatches (GroupId, UserId)
SELECT geue.GroupExtensionId, geue.UserExtensionId
FROM ADGroup adg
JOIN GroupExtension ge ON adg.Id = ge.ADGroupId
JOIN GroupExtensionUserExtension geue ON ge.Id = geue.GroupExtensionId
WHERE (#GroupId IS NULL OR ge.Id = #GroupId)
AND (#GroupName IS NULL OR adg.[Name] LIKE #GroupName + '%')
END
ELSE
BEGIN
SELECT
au.*,
0 HasExtendedSecurity
FROM
AllUsers au
JOIN
Domain d ON au.DomainName = d.[Name]
WHERE
(#DomainId IS NULL OR au.DomainId = #DomainId) AND
(#DomainName IS NULL OR au.DomainName = #DomainName) AND
(#NetworkUserId IS NULL OR au.NetworkUserId = #NetworkUserId) AND
(#UserPrincipalName IS NULL OR au.UserPrincipalName = #UserPrincipalName) AND
(#FirstName IS NULL OR au.FirstName LIKE #FirstName + '%') AND
(#LastName IS NULL OR au.LastName LIKE #LastName + '%' ) AND
(#EmailAddress IS NULL OR au.Email LIKE #EmailAddress + '%')
END
END

Passing Parameters to a stored Procedure

I am working on a project that accepts 3 different parameters, the date is required and the First and Last name are optional. We setup the query below, but even if I change the parameters on the report (SSRS) it still looks at #LetterCreated as being '1/1/1950', any ideas on how I can get this to just accept the parameters? We set the date this way because we want the report to show with all of the reports when it is initially opened.
Alter Proc
AS
BEGIN
SET NOCOUNT ON;
DECLARE #LetterCreated DATETIME,
#FirstName VARCHAR(20),
#LastName VARCHAR(20)
SELECT #LetterCreated = '1/1/1950'
SELECT #FirstName = ''
SELECT #LastName = ''
SELECT
LETTERCREATETIME,
Firstname,
LastName,
From RedFlagAddress
WHERE
CASE WHEN #LetterCreated='1/1/1950'
THEN '1/1/1950'
ELSE ISNULL(LETTERCREATETIME, '07/05/81')
END = #LetterCreated
AND (LastName LIKE #LASTNAME + '%' AND FirstName LIKE #FirstNAME + '%')
END
Any suggestions would be greatly appreciated.
You are setting the #lettercreated date in the procedure. Variables defined within the procedure are not visible outside it.
You should declare the parameters as parameters, and set the default in the declaration
ALTER PROC yourproc
(
#LetterCreated DATETIME = '1950-1-1',
#FirstName VARCHAR(20) = '',
#LastName VARCHAR(20) = ''
)
as
begin
select
LETTERCREATETIME,
Firstname,
LastName,
From
RedFlagAddress
where
(
ISNULL(LETTERCREATETIME, '07/05/81') = #LetterCreated
or
#LetterCreated = '1950-1-1'
)
AND LastName LIKE #LASTNAME + '%'
AND FirstName LIKE #FirstNAME + '%'
end
I'm guessing here but what you may want is
IF parameter #LetterCreated is null then it should not be used as a filter at all
IF the data in RedFlagData.LETTERCREATETIME is Null then it should be matched to a filter date of '07/05/81' FWR
Assuming that you have the 'allow nulls' check on the RDL/RDLC set for the #LetterCreated parameter, the where needs to be changed, the optional filter can be set like so:
ISNULL(#LetterCreated, LETTERCREATETIME) = ISNULL(LETTERCREATETIME, '07/05/81')
If you get rid of the magic date, then you can guarantee no date filter applied even if LETTERCREATETIME is null, by the filter:
ISNULL(#LetterCreated, LETTERCREATETIME) = ISNULL(LETTERCREATETIME)
OR
(#LetterCreated IS NULL AND LETTERCREATETIME IS NULL)
Thus:
ALTER PROC XYZ
(
#LetterCreated DATETIME,
#FirstName VARCHAR(20) = NULL,
#LastName VARCHAR(20) = NULL
)
as
begin
select
LETTERCREATETIME,
Firstname,
LastName,
From
RedFlagAddress
where
(
ISNULL(#LetterCreated, LETTERCREATETIME) = LETTERCREATETIME
OR
(#LetterCreated IS NULL AND LETTERCREATETIME IS NULL)
)
AND LastName LIKE ISNULL(#LastName, '') + '%'
AND FirstName LIKE ISNULL(#FirstName, '') + '%'
end
One caveat : The performance of this query will be terrible, given the amount of functional manipulation in the where clause, and the LIKEs and ORs - Hopefully RedFlagAddress is a relatively small table? If not, you may need to rethink your approach
Similar to podiluska's answer, you should set the parameters as part of the SP, as podiluska indicates, but then you should set the default values in SSRS, in the Parameters there.
This will let the users see the defaults and use those for subscriptions, or override them as needed.
Alter Proc Proc_Name
(
#LetterCreated DATETIME,
#FirstName VARCHAR(20) = null,
#LastName VARCHAR(20) = null
)
AS
BEGIN
SET NOCOUNT ON;
This will pass null values as Default values to you Proc now you code should be able to handle null values if no values are provided for FirstName and LastName

Search ID, first name and last name in SQL using Like

Hi I have this stored procedure for Searching employee information. I want the user to have the choice to enter ID, or First Name or Last Name. but when I execute this stored procedure, it requires the other parameters.
create proc searchtry
#empID int,
#firstname varchar(20),
#lastname varchar(20)
as
begin
select fld_EmployeeId,fld_EmployeeFirstName,fld_EmployeeLastName
from Reference.tbl_EmployeeDetails
where fld_EmployeeId like #empID
OR fld_EmployeeFirstName like #firstname
OR fld_EmployeeLastName like #lastname
end
You should give default values to the parameters
create proc searchtry
#empID int = NULL,
#firstname varchar(20) = '',
#lastname varchar(20) = ''
as
begin
select fld_EmployeeId,fld_EmployeeFirstName,fld_EmployeeLastName
from Reference.tbl_EmployeeDetails
where fld_EmployeeId like #empID
OR fld_EmployeeFirstName like #firstname
OR fld_EmployeeLastName like #lastname
end

Stored Procedure take either or variables?

I'm working in sql server 2005 here and I wanted to know if there was a way to make a stored procedure take variable a or variable b for its parameters.
Right now if I declare A and B it requires both A and B. Possible to make it take A or B instead? So that if the other one doesn't have a value it uses the other?
ex:
#ID VARCHAR(255)
#MAKE VARCHAR(255)
AS
BEGIN
SET NOCOUNT ON
SELECT *
FROM CARS
WHERE ID = #ID OR MAKE =#MAKE
Thanks!
create procedure MyProcedure
(
#ID VARCHAR(255) = NULL,
#MAKE VARCHAR(255) = NULL
)
AS
SET NOCOUNT ON
SELECT *
FROM CARS
WHERE
(#ID IS NOT NULL AND ID = #ID)
OR
(#MAKE IS NOT NULL AND MAKE =#MAKE)
IF ID IS NULL
BEGIN
/*Code goes here*/
END
ELSE IF MAKE IS NULL
BEGIN
/*More code goes here*/
END
ELSE
BEGIN
/*Even more code goes here*/
END
I'm quite sure you can call a function using NULL.
And, also do this:
#ID VARCHAR(255) = NULL
#MAKE VARCHAR(255) = NULL
Read this: http://weblogs.asp.net/stanleygu/archive/2010/02/08/solution-5-implementing-optional-parameters-in-t-sql-stored-procedures.aspx
Stored procedures can take optional arguments.
create procedure mysp
#a varchar(255) = NULL,
#b varchar(255) = NULL
as begin
select *
from cars
where (a = #a and #a is not NULL) or
(b = #b and #b is not NULL);
end;