Procedure to check annual date - sql

I'm trying to create a procedure to verify annual dates. The date is stored one time in the BD, but in the calendar on my winform it shows annually(I use annually bolded dates in C#). So what I want to do with the query, is to check is the month and the day are like the date stored in the table, but does not work. This is my query:
SELECT IdCalendar,
Description,
DateCalendar,
Annualy
FROM Calendar
WHERE
(DATEPART(MONTH,DateCalendar) like DATEPART(MONTH,#DateCalendar)) AND
(DATEPART(DAY,DateCalendar) like DATEPART(DAY,#DateCalendar))
And for example, my stored DateCalendar is '2015-12-04', and I my paramenter #DateCalendar is '2016-12-04'. Any idea about how to do a better query?
EDIT
The query does not have any error or warning. Just returns 0 rows. And my DateCalendar is stored as DateTime.
The SP:
CREATE PROC [dbo].[usp_app_Calendar_Search]
#DateCalendar DATETIME,
#Result SMALLINT OUTPUT,
#Message VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #vResult SMALLINT, #vMessage VARCHAR(1000)
SELECT #vResult = 0, #vMessage = ''
BEGIN TRY
IF EXISTS (SELECT * FROM Calendar WHERE DateCalendar = #DateCalendar)
BEGIN
IF(#DateCalendar = 0) SET #DateCalendar = NULL
SELECT IdCalendar,
Description,
DateCalendar,
Annualy
FROM Calendar
WHERE
(DATEPART(MONTH,DateCalendar) like DATEPART(MONTH,#DateCalendar)) AND
(DATEPART(DAY,DateCalendar) like DATEPART(DAY,#DateCalendar))
SET #vResult = 1
SET #vMessage = 'Done'
END
ELSE BEGIN
SET #vResult = 0
SET #vMessage = 'Error.'
END
END TRY
BEGIN CATCH
SET #vResult = -1
SET #vMessage = 'Error: ' + ERROR_MESSAGE() + ' Line: ' + CAST(ERROR_LINE() AS VARCHAR)
END CATCH
SELECT #Result = #vResult, #Message = #vMessage
END
Thanks in advance.

The problem is with IF EXISTS (SELECT * FROM Calendar WHERE DateCalendar = #DateCalendar). I rewrite your SP:
CREATE PROC [dbo].[usp_app_Calendar_Search]
#DateCalendar DATETIME,
#Result SMALLINT OUTPUT,
#Message VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #vResult SMALLINT = 0
,#vMessage VARCHAR(1000) = '';
IF(#DateCalendar = 0) SET #DateCalendar = NULL;
BEGIN TRY
SELECT IdCalendar,
Description,
DateCalendar,
Annualy
FROM Calendar
WHERE DATEPART(MONTH,DateCalendar) = DATEPART(MONTH,#DateCalendar)
AND DATEPART(DAY,DateCalendar) = DATEPART(DAY,#DateCalendar);
IF ##ROWCOUNT > 0
SELECT #vResult = 1, #vMessage = 'Done'
ELSE
SELECT #vResult = 0, #vMessage = 'Error.';
END TRY
BEGIN CATCH
SET #vResult = -1
SET #vMessage = 'Error: ' + ERROR_MESSAGE() + ' Line: '
+ CAST(ERROR_LINE() AS VARCHAR)
END CATCH
SELECT #Result = #vResult, #Message = #vMessage;
END
EDIT:
Now the WHERE condition is not-SARGable so it means that query optimizer will skip index on DateCalendar column (if exists any).
You can use computed columns like #Tom Page suggested in comment:
ALTER TABLE Calendar ADD MonthCalendar AS DATEPART(MONTH,DateCalendar);
ALTER TABLE Calendar ADD DayCalendar AS DATEPART(day,DateCalendar);
/*Create Index on Calculated Columns for Month and day*/
CREATE INDEX IX_Calendar_Month_Day ON Calendar(MonthCalendar , DayCalendar);
/*Use Computed Column Index in W*/
DECLARE #DateCalendar datetime = '2015-12-25';
SELECT IdCalendar, Description, DateCalendar, Annualy
FROM Calendar
WHERE MonthCalendar = DATEPART(MONTH,#DateCalendar)
AND DayCalendar = DATEPART(DAY,#DateCalenda);

Related

What's the limit of a variable in T-SQL? Why does my variable prints out as NULL?

I'm creating a stored procedure with the following code:
CREATE OR ALTER PROCEDURE Insert_Into_Table
#Origin VARCHAR(255),
#Destination VARCHAR(255),
#Origin_Columns VARCHAR (4000),
#Destination_Columns VARCHAR (4000),
#Delete_Date_Column_Name VARCHAR(63), --Nullable
#Delete_Period_Months INT -- Nullable
AS
BEGIN TRY
DECLARE #insert_query VARCHAR(4000) = NULL;
DECLARE #delete_query VARCHAR(4000) = NULL;
DECLARE #check_query VARCHAR (4000) = NULL;
DECLARE #Date_To_Delete DATETIME = CAST(DATEADD(MONTH, -#Delete_Period_Months, GETDATE()) AS DATETIME);
-- Table names cannot be referenced directly in SPs, so we bypass
-- this issue by declaring a variable containing the query
IF #Delete_Date_Column_Name IS NOT NULL
OR #Delete_Period_Months IS NOT NULL
SET #delete_query = 'DELETE FROM ' + #Destination + ' WHERE ' +
#Delete_Date_Column_Name + ' >= ' + CONCAT(CHAR(39),CAST(#Date_To_Delete AS VARCHAR(255)),CHAR(39));
ELSE
PRINT N'Missing or no values provided for table deletion. Only executing copy';
CREATE TABLE #temptable (count INT)
SET #check_query = 'INSERT INTO #temptable SELECT TOP 1 1 AS count FROM ' + #Origin
EXECUTE(#check_query)
SET #insert_query = 'INSERT INTO' + QUOTENAME(#Destination) + QUOTENAME(#Destination_Columns, '()') +
'SELECT ' + #Origin_Columns + ' FROM ' + QUOTENAME(#Origin);
BEGIN TRY
IF EXISTS (SELECT TOP 1 * FROM #temptable)
BEGIN TRANSACTION
EXECUTE(#delete_query);
EXECUTE(#insert_query);
COMMIT
END TRY
BEGIN CATCH
ROLLBACK;
THROW 51000, 'The Origin table is empty', 1;
END CATCH
END TRY
BEGIN CATCH
THROW 51000, 'Error creating transaction', 1;
END CATCH
GO
When executing the stored proecedure with the parameters shown, it works correctly:
EXEC Insert_Into_Table
#Origin = 'Sink_Proc',
#Destination = 'Sink_Test',
#Origin_Columns = 'customer, order_number, created_date',
#Destination_Columns = 'customer, order_number, created_date',
#Delete_Date_Column_Name = NULL,
#Delete_Period_Months = NULL
However, when executing it with 25+ columns as Origin/Destination columns, when I print the #insert_query variable, it returns NULL and no operation is done. Why is this happening?

Delete a row from a table in SQL Server and set message for every condition

I have set #message var, and I want to set those message as per conditions but whenever I execute this code it only returns one message which I set
#Message = 'Please provide Topic Name and Topic ID'
Please help me - thanks in advance
ALTER PROCEDURE DeleteTopicNameWebAPI
#InstituteID bigint = 0 ,
#SubjectID bigint = 0,
#TopicName nvarchar(200) = null,
#TopicID bigint = 0
AS
BEGIN
DECLARE #Message nvarchar(200)
IF EXISTS (SELECT 1 FROM TopicMaster
WHERE TopicID = #TopicID AND TopicName = #TopicName AND InstituteID = #InstituteID)
BEGIN
SET #Message = 'Topic name is present in a system'
END
ELSE
BEGIN
SET #Message='Topic Name is not present in a system with Topic ID :'+' '+ Convert(nvarchar (20),#TopicID) + ' And Topic Name :' +' '+#TopicName;
END
IF #TopicID = 0 AND #TopicName IS NULL
BEGIN
DELETE FROM TopicMaster
WHERE InstituteID = #InstituteID
AND CategoryID = #SubjectID
AND TopicName = #TopicName
AND TopicID = #TopicID;
SET #Message ='Done'
END
ELSE
BEGIN
SET #Message = 'Please Provide Topic Name and Topic ID. '
END
SELECT #Message AS [Message]
END
You're overwriting the message. You should append to it instead:
declare #message nvarchar(max) = '';
set #message += 'Now hear this.';
set #message += 'I am hungry.';
Then probably print it out if successful or throw it if not. Don't select it:
print (#message); // or
throw 50000, #message, 1;

Generate Next Alphanumeric Code on SQL Server

I need to create a consecutive sequence of varchar(5) (always 5 chars only) code starting from PREVIOUS code.
For example
'00000', '00001', '00002'...'00009', '0000A', '0000B'...'0000Z', '00010','00011'...'ZZZZZ'.
So if I have #PREVIOUS_CODE = '00000', #NEXT_CODE will be '00001'.
If I have #PREVIOUS_CODE = '00009', #NEXT_CODE will be '0000A'
If I have #PREVIOUS_CODE = '0000Z', #NEXT_CODE will be '00010'
So I need something like that
USE [DATABASE]
GO
CREATE PROCEDURE [dbo].[spGetNextCode]
#PREVIOUS_CODE VARCHAR(5)
AS
DECLARE #NEXT_CODE VARCHAR(5)
DO STUFF
...
SELECT #NEXT_CODE AS NEXT_CODE
GO
Any Help?
Just keep an integer counter in the same table and convert it. I'm using the following SQL Server function in one of my applications:
CREATE FUNCTION [dbo].[GetAlphanumericCode]
(
#number BIGINT,
#leadingzeroes INT = 0
)
RETURNS varchar(255)
AS
BEGIN
DECLARE #charPool varchar(36)
SET #charPool = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
DECLARE #result varchar(255)
IF #number < 0
RETURN ''
IF #number = 0
SET #result = '0'
ELSE BEGIN
SET #result = ''
WHILE (#number > 0)
BEGIN
SET #result = substring(#charPool, #number % 36 + 1, 1) + #result
SET #number = #number / 36
END
END
IF #leadingzeroes > 0 AND len(#result) < #leadingzeroes
SET #result = right(replicate('0', #leadingzeroes) + #result, #leadingzeroes)
RETURN #result
END
It should be a trivial task to rewrite it as a stored procedure

The MIN function requires 1 argument(s)

Below is the code snippet in which MIN function using. When execute below code it is giving an error.
CREATE FUNCTION [dbo].[FN_TempCalcTransportExemp]
(
#EmployeeID varchar(20),
#PayElement varchar(20),
#Month varchar(10),
#FinYear varchar(10)
)
RETURNS decimal
AS
BEGIN
DECLARE #TarnsportExemption decimal(18,2) = 0
DECLARE #TDSIsFullExemption bit
DECLARE #PermanentPhysicalDisability decimal(18,2) = 0
DECLARE #UsingComapnyCar bit
DECLARE #Conveyance decimal(18,2) = 0
DECLARE #TransYes decimal(18,2) = 0
DECLARE #TransNo decimal(18,2) = 0
DECLARE #MinConveyance decimal(18,2) = 0
DECLARE #MinTransport decimal(18,2) = 0
SELECT
#TDSIsFullExemption = TDSDetailsFullExemption,
#TransYes = TDSDetailsYes,
#TransNo = TDSDetailsNo
FROM
tbl_TDSSettingDetails
WHERE
TDSSettingsDetailID = 2
SELECT
#Conveyance = #Month
FROM
tbl_Income
WHERE
EmployeeID = #EmployeeID
AND Element = #PayElement
AND FinancialYear = #FinYear
SELECT
#UsingComapnyCar = UsingCompanyCar,
#PermanentPhysicalDisability = PermanentPhysicalDisability
FROM
tbl_Employee_TDS
WHERE
EmployeeID = #EmployeeID
AND TDSFinancialYear = #FinYear
IF (#TDSIsFullExemption = 1)
BEGIN
SET #TarnsportExemption = #Conveyance
END
ELSE
BEGIN
IF (#UsingComapnyCar = 1)
BEGIN
IF (#Conveyance = 0)
BEGIN
SET #MinConveyance = 0
END
ELSE
BEGIN
SET #MinConveyance = #Conveyance
END
IF (#PermanentPhysicalDisability = 1)
BEGIN
SET #MinTransport = #TransYes
END
ELSE
BEGIN
SET #MinTransport = #TransNo
END
SET #TarnsportExemption = MIN(#MinConveyance, #MinTransport)
END
ELSE
BEGIN
SET #TarnsportExemption = 0
END
END
RETURN #TarnsportExemption
END
Error Message:
Msg 174, Level 15, State 1, Procedure FN_TempCalcTransportExemp, Line
66
The MIN function requires 1 argument(s).
set #TarnsportExemption = MIN(#MinConveyance,#MinTransport) - The MIN function is not what you think it is.
You probably want to do something like this:
set #TarnsportExemption = CASE WHEN #MinConveyance < #MinTransport THEN
#MinConveyance
ELSE
#MinTransport
END
Another option is this:
SELECT #TarnsportExemption = MIN(val)
FROM
(
SELECT #MinConveyance as val
UNION ALL
SELECT #MinTransport as val
)
And one more option is to use the values clause:
SELECT #TarnsportExemption = MIN(val)
FROM (VALUES ( #MinConveyance), (#MinTransport)) AS value(val)
Change your min statement like below MIN. Please refer MIN (Transact-SQL)
--fROM
set #TarnsportExemption = MIN(#MinConveyance,#MinTransport)
--To
SELECT #TarnsportExemption = MIN(A) FROM (
SELECT #MinConveyance A
UNION ALL
SELECT #MinTransport
)AS AA
In SQL, MIN function will return you minimum value of a column from selected list; so you can use MIN only in inline queries.
e.g. Select min(Salary) from Tbl_Employee
So, in your case either you can use case when then or union all to get minimum value from two variables as:-
SET #TarnsportExemption = CASE WHEN #MinConveyance < #MinTransport THEN #MinConveyance ELSE #MinTransport END
OR
SELECT #TarnsportExemption = MIN(TEMPS.[VALUE])
FROM (
SELECT #MinConveyance AS VALUE
UNION ALL
SELECT #MinTransport AS VALUE
) AS TEMPS

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