SQL: search for null date - sql

I have a select procedure that search my Members table.
The Members table has:
ID – Name – Deleted
1 – Marcus – NULL
2 – Regina – 2014-03-26 09:33:00.000
Being: ID a PK int no NULL, Name a varchar(250) and Deleted a datetime NULL.
Here’s my procedure:
CREATE PROCEDURE dbo.SELECT_MEMBERS
#ID int = NULL,
#Name varchar(250)= NULL,
#Deleted datetime =NULL
AS
BEGIN
IF #Deleted = ''
BEGIN
SET #Deleted = NULL
END
ELSE
BEGIN
SET #Deleted = #Deleted
END
SET NOCOUNT ON;
SELECT ID, Name, Deleted
FROM dbo.Members WHERE
(#ID IS NULL OR #ID = ID)
AND (#Name IS NULL OR #Name = Name)
AND (#Deleted IS NULL OR #Deleted = Deleted)
END
GO
In order to search for the members that have no deleted date (if they have a deleted date means that they are no active members) I do:
EXEC dbo.SELECT_MEMBERS #Deleted = ''
But this is not working as I get the row with a deleted date inserted.
What am I doing wrong?
Thanks a lot!!

CREATE PROCEDURE dbo.SELECT_MEMBERS
#ID int = NULL,
#Name varchar(250)= NULL,
#Deleted datetime =NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT ID, Name, Deleted
FROM dbo.Members
WHERE ID = ID
AND ISNULL(#Name, '') = ISNULL(Name, '')
AND ISNULL(#Deleted, '') = ISNULL(Deleted, '')
END
GO

It seems that you want an empty/NULL value for #Deleted date to behave differently from a NULL value for #ID and #Name: you want the actual comparison for #Deleted to be true only when the value is NULL.
I think you want something like this:
CREATE PROCEDURE dbo.SELECT_MEMBERS
#ID int = NULL,
#Name varchar(250)= NULL,
#Deleted datetime = NULL
AS
BEGIN
SELECT ID, Name, Deleted
FROM dbo.Members
WHERE (#ID IS NULL OR #ID = ID) AND
(#Name IS NULL OR #Name = Name) AND
((#Deleted IS NULL OR #Deleted = Deleted or #Deleted = '' and Deleted is null)
END;

Related

All records being deleted when deleting records from a temp table

I have a stored procedure that I am passing a string of documentIDs to and its supposed to delete the documentID where its roleID = #roleID, but instead it is deleting all the records based on the roleID and all I want to do is delete the documentIDs from the table based on the roleID
My sp is
ALTER PROCEDURE sp_RemoveDocumentIDsFromRole
(
#roleID int,
#group_name varchar(50),
#DocumentIDString varchar(500),
#group_display_name varchar(50)
)
as
UPDATE [master_groups]
set group_name = #group_name, #group_display_name = #group_display_name
where roleID = #roleID
-- Creating Variables
DECLARE #numberLength int
DECLARE #numberCount int
DECLARE #TheDocumentIDs VarChar(500)
DECLARE #sTemp VarChar(100) -- to hold single characters
-- Creating a temp table
DECLARE #T TABLE
(
TheDocumentIDs VarChar(500)
)
--Initializing Variables for counting
SET #numberLength = LEN (#DocumentIDString)
SET #numberCount = 1
SET #TheDocumentIDs = ''
--Start looping through the keyword ids
WHILE (#numberCount <= #numberLength)
BEGIN
SET #sTemp = SUBSTRING (#DocumentIDString, #numberCount, 1)
IF (#sTemp = ',')
BEGIN
INSERT #T(TheDocumentIDs) VALUES (#TheDocumentIDs)
SET #TheDocumentIDs = ''
END
IF (#sTemp <> ',')
BEGIN
SET #TheDocumentIDs = #TheDocumentIDs + #sTemp
END
SET #numberCount = #numberCount + 1
END
declare #rLevel int
set #rLevel = 0
delete from [master_group_document_relations] where exists(select documentID = #TheDocumentIDs from #T) and roleID = #roleID
UPDATE: SAMPLE DATA
Not sure what you get in #TheDocumentIDs, but I suppose it should work for you.
First of all as #Chris mentioned, you should check put condition to where clause and as documentIds is a list of id's it should used with IN condition and not equality, that's why you need or use sp_executesql or fill id's to a temp table.
EXECUTE sp_executesql
N'delete from [master_group_document_relations]
where documentID IN (#TheDocumentIDs)
and roleID = #roleID',
N'#TheDocumentIDs varchar(500), #roleID int',
#DocumentIDString,
#roleID;
Or try this
delete from [master_group_document_relations]
where documentID IN (SELECT TheDocumentIDs FROM #T)
and roleID = #roleID
If you want to delete records of master_group_document_relations where its documentID is in TheDocumentIDs of #t and roleID is equal to #roleID then try this :
DELETE T1
FROM [master_group_document_relations] AS T1
WHERE EXISTS(SELECT 1
FROM #T AS T2
WHERE T1.documentID = T2.TheDocumentIDs)
AND roleID = #roleID

Sql Server Stored Procedure Case When in Update

I am new in stored procedures.
ALTER PROCEDURE [dbo].[SP_MY_STORE_PROCEDURED]
(
#ID INT,
#NAME VARCHAR(50)
)
AS
BEGIN
UPDATE MY_TABLE
SET
WHEN
(( ID ) > 1)
THEN
ID=#ID
,
NAME = #NAME
END
I try to use when then for update my ID and Name
If Id is greater than 1 i want to update otherwise no update.
How can i do it ms sql?
Any help will be appreciated.
Thanks.
I think this is what you are after:
ALTER PROCEDURE [dbo].[SP_MY_STORE_PROCEDURED]
(
#ID INT,
#NAME VARCHAR(50)
)
AS
BEGIN
UPDATE MY_TABLE
SET NAME = #NAME
WHERE ID = #ID
END
You do not need to check ID>1 since you are checking the equality with #ID. If you want to be sure that this doesn't happen if #ID <=1 then you may try the following:
ALTER PROCEDURE [dbo].[SP_MY_STORE_PROCEDURED]
(
#ID INT,
#NAME VARCHAR(50)
)
AS
BEGIN
IF #ID > 1
UPDATE MY_TABLE
SET NAME = #NAME
WHERE ID = #ID
END
I'm not sure exactly what you're trying to update. Are you trying to change the name on a user record with id = #ID?
ALTER PROCEDURE [dbo].[SP_MY_STORE_PROCEDURED]
(
#ID INT,
#NAME VARCHAR(50)
)
AS
BEGIN
UPDATE MY_TABLE
SET Name = #Name
WHERE Id = #ID and #ID > 1
END
This should do it.
ALTER PROCEDURE [dbo].[SP_MY_STORED_PROCEDURE] ( #ID INT, #NAME VARCHAR(50) )
AS
BEGIN
IF #ID > 1
UPDATE MY_TABLE
SET Name = #Name
WHERE Id = #ID
END

Issues with Trigger on insert (t-sql)

Say I have a self relation table as following :
ID - Name - ParentID
Now everytime that users insert sth in this table I would like to check if the Name inserted is already in the
rows where ParentID equals to the inserted one , if true then rollback the transaction.
But the problem is when I check the rows with the parentID from the inserted table the inserted row is already in the main table too. So, the trigger always rolls back the transaction.
Here is my trigger :
ALTER TRIGGER TG_Check_Existance_In_myTbl
ON myTbl FOR INSERT,UPDATE AS
DEClARE #result BIT
DECLARE #numberOfRows INT
DECLARE #counter INT
DECLARE #names nVARCHAR (30)
DECLARE #name NVARCHAR (30)
SET #result = 0
SET #numberOfRows = (SELECT COUNT (Name)
FROM myTbl
WHERE ParentID IN
(
SELECT ParentID
FROM inserted
)
)
SET #counter = 1;
SELECT #name = Name
FROM inserted
WHILE (#counter <= #numberOfRows)
BEGIN
WITH Q
AS
(
SELECT ROW_NUMBER()
OVER (ORDER BY Name) 'Row', Name
FROM myTbl WHERE ParentID IN
(
SELECT ParentID
FROM inserted
)
)
SELECT #names = Name
FROM Q
WHERE Row = #counter
IF #name = #names
SET #result=1;
SET #counter = #counter + 1
END
IF #result = 1
ROLLBACK TRAN
Unless I am missing something you are making this way too hard.
Why don't you use a unique constraint on the two columns?
table_constraint (Transact-SQL)

Does this query require dynamic sql? SQL Server

I want to select the parameters of a stored procedure and then check whether each parameter is null or not in a loop.
The problem I'm having is that when I want to evaluate the variable in the IF statement, it is not being evaluated correctly. I want to evaluate each parameter I stored in the table variable. I don't know the syntax for this...or maybe it isn't even possible?
Does this require Dynamic SQL? If so, when executing dynamic sql, the value of the variable will be out of scope so how do I deal with that?
I verified everything up to the IF statement works.
CREATE PROCEDURE dbo.UpdateBank
(
#BankKey [smallint] = NULL,
#Bank [varchar] (30) = NULL,
#BankCode [char] (4) = NULL,
#MasterBankCode [char] = NULL,
#Bin [char] (6) = NULL,
#WebSite [varchar] (50) = NULL,
#isActive [bit] = NULL,
#CreateDate [smalldatetime] = NULL
)
AS
SET NOCOUNT ON
SET ANSI_NULLS OFF
DECLARE #MaxRow TINYINT, #Count TINYINT
DECLARE #SPName VARCHAR (128), #CurrentRow TINYINT
SET #SPName = OBJECT_NAME(##PROCID) -- SP self-reference to find its current name
DECLARE #SPParametersList TABLE (ID INT Identity(1,1) Primary Key,
ParameterName NVARCHAR (128),
DataType NVARCHAR (128),
ParameterMode NVARCHAR (10))
CREATE TABLE #TempExec(ID INT Identity(1,1) Primary Key,
Num BIT)
INSERT INTO #SPParametersList (ParameterName, Datatype, ParameterMode)
SELECT PARAMETER_NAME,DATA_TYPE,PARAMETER_MODE
FROM INFORMATION_SCHEMA.PARAMETERS
WHERE SPECIFIC_NAME = #SPName
SET #CurrentRow = 1
SELECT #MaxRow = ISNULL(MAX(ID),0) FROM #SPParametersList
WHILE #CurrentRow <= #MaxRow
BEGIN
IF ((SELECT ParameterName FROM #SPParametersList WHERE ID = #CurrentRow) <> NULL)
BEGIN
SELECT 'Success'
SET #Count = #Count + 1
END
SELECT 'Fail'
SET #CurrentRow = #CurrentRow + 1
END
SELECT #Count
I always get 'Fail' when I run this stored proc
Change your line:
IF ((SELECT ParameterName FROM #SPParametersList WHERE ID = #CurrentRow) <> NULL)
to
IF ((SELECT ParameterName FROM #SPParametersList WHERE ID = #CurrentRow) IS NOT NULL)
You also need to initialize the #Count variable to 0:
SET #Count = 0
SET #CurrentRow = 1
SELECT #MaxRow = ISNULL(MAX(ID),0) FROM #SPParametersList
Probably the issue is in the <> NULL which should
IF EXISTS(SELECT ParameterName FROM #SPParametersList WHERE ID = #CurrentRow)
but I'm not sure what you want to achieve with that piece of code...
I suspect that this is an example of a query that can be rewritten without the use of loops/cursors (most sql is in my experience...)
Does the query below give you your desired results?
with temp as
(
SELECT '#BankKey' as ParamName
UNION
SELECT '#Bank'
)
SELECT COUNT(*) as myCount
FROM INFORMATION_SCHEMA.PARAMETERS as isp
LEFT JOIN temp as t
ON t.ParamName = isp.PARAMETER_NAME
WHERE SPECIFIC_NAME = #SPName AND t.ParamName is null
You should try to avoid using Loops/Cursors as much as possible. SQL Server (and most DBMSs in general) are excellent at performing Set based operations and terrible at performing row based operations (loops/cursors).
(1) "I always get 'Fail' when I run this stored proc": you have forget the ELSE branch
IF ((SELECT ParameterName FROM #SPParametersList WHERE ID = #CurrentRow) /*<>*/ IS NOT NULL)
BEGIN
SELECT 'Success'
SET #Count = #Count + 1
END
ELSE -- << here
BEGIN
SELECT 'Fail'
END
SET #CurrentRow = #CurrentRow + 1
(2) To count all not null parameters:
SELECT #Count=COUNT(*)
FROM #SPParametersList a
WHERE a.ParameterName IS NOT NULL
To count all null parameters:
SELECT #Count=COUNT(*)
FROM #SPParametersList a
WHERE a.ParameterName IS NULL
Note: if you want to test for NULL / NOT NULL you should use column/#variable IS [NOT] NULL operator and SET ANSI_NULLS must be ON: SET ANSI_NULLS ON.

Selecting not null column

I have a table with varbinary(max) column and nvarchar(max) column. One of them is null and the other has a value.
I would like to return the column that has the value as a varbinary(max) column. So far I have tried this, that does not work:
SELECT
A =
CASE A
WHEN NULL THEN B
ELSE A
END
FROM Table
SELECT COALESCE(A, CAST(B As varbinary(max)))
UPDATE: In response to comments (thanks) and assuming B is the nvarchar(max) column, I have moved the CAST inside the COALESCE
Try SELECT ISNULL(A, cast(B AS varbinary(max))) FROM TABLE
Your case statement evaluates to the dreaded A = NULL:
CASE A WHEN NULL THEN B ELSE A END
Is the same as:
CASE WHEN A = NULL then B ELSE A END
One way to fix this is to use A IS NULL, like:
CASE WHEN A IS NULL THEN B ELSE A END
Or even simpler:
COALESCE(A,B)
Both the when and the coalesce will assume the data type of the first argument. To cast the result to varbinary, you can place the varbinary column first, or explicitly cast:
COALESCE(CAST(A AS VARBINARY(MAX)),B)
here is the full code of create table and insert value and apply my code and only retrieve not null value
CREATE TABLE [dbo].[SUPPLIER](
[ID] [int] IDENTITY(1,1) NOT NULL,
[SUPPLIER_NAME] [varchar](100) NOT NULL,
[ADDRESS] [varchar](150) NULL,
[CREATE_DATE] [datetime] NULL,)
INSERT INTO [MyPayrol].[dbo].[SUPPLIER]
([SUPPLIER_NAME]
,[CREATE_DATE])
VALUES
('Khaled Nabil'
,GETDATE())
declare #inumberofcolumn int
select #inumberofcolumn= count(*)
from sys.columns where OBJECT_NAME(object_id) = 'supplier'
declare #nameofcolumn varchar(100)
set #nameofcolumn =''
declare #counter int
set #counter=1
declare #colname varchar(100)
declare #statment varchar(100)
declare #value varchar(100)
while #counter <=#inumberofcolumn
begin
select #colname= COL_NAME(object_id('[dbo].[SUPPLIER]'),#counter)
declare #data table ([value] varchar(100))
--set #statment = 'select '+#colname+' from [dbo].[SUPPLIER]'
insert #data exec ('SELECT top 1 '+ #colname +' from [dbo].[SUPPLIER]')
select #value = [value] from #data
if #value is not null
begin
if #counter = 1
begin
set #nameofcolumn = #nameofcolumn + #colname
end
else
begin
set #nameofcolumn = #nameofcolumn + ','+ #colname
end
end
set #counter = #counter+1
end
execute ('select '+#nameofcolumn+' from [dbo].[SUPPLIER]')