t-sql conditional date processing - tsql

I have a stored procedure which returns data used in a report. There are numerous paramters the user can specify, two of which are a start and end date. I can use a WHERE create_date BETWEEN #arg_start AND #arg_end statement to filter on the dates.
What I dont know how to do is to handle the situation where the user doesnt supply any dates. CASE doesnt support anything like WHERE create_date = CASE #arg_start WHEN NULL THEN create_date ELSE BETWEEN #arg_start AND #arg_end.
I've done a lot of research on google, msdn, and here and I haven't find out to handle conditional null datetime processing. Although I know its bad form, I can pass programatically pass in a magic date, such as 1/1/1900, to test instead of a null, but that doesn't really help in conditional date processing.

Make it a multi-part condition:
WHERE
(#argstart IS NULL AND #argend IS NULL)
OR (#argend IS NULL AND create_date > #Argstart)
OR (#argstart IS NULL AND create_date < #argend)
OR (Createdate BETWEEN #Argstart AND #Argend)

Something like this:
where (create_date >= #arg_start or #arg_start is null) and
(create_date <= #arg_end or #arg_end is null)
If you are on SQL Server 2008 you should use OPTION (RECOMPILE). Ref: Dynamic Search Conditions in T-SQL
Version for SQL 2008 (SP1 CU5 and later).
Otherwise you might be better of using the answer provided by JNK.

I would make the default values for the stored procedure parameters the "magic dates":
CREATE PROC usp_report
#StartDate datetime = '1900-01-01',
#EndDate datetime = '9999-12-31'
AS
SELECT *
FROM MyTable
WHERE DateField BETWEEN #Startdate AND #EndDate
In your application, if the user has not specified a date, don't pass that parameter to the stored proc.
This would keep your application code clean, and give you the data you need.

Related

Using DDL, how can the default value for a Numeric(8,0) field be set to today's date as YYYYMMDD?

I'm trying to convert this, which works:
create_timestamp for column
CREATETS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
to something that works like this, but this code is not working:
date_created for column
DTCREATE NUMERIC(8,0) NOT NULL DEFAULT VARCHAR_FORMAT(CURRENT_TIMESTAMP, 'YYYYMMDD'),
Can anyone advise DDL to accomplish what I'm going for? Thank you.
When asking for help with Db2, always specify your Db2-server platform (Z/OS , i-series, linux/unix/windows) and Db2-server version, because the answer can depend on these facts.
The default-clause for a column does not have syntax that you expect, and that is the reason you get a syntax error.
It's can be a mistake to store a date as a numeric, because it causes no end of hassle to programmers and reporting tools, and data exchange. It's usually a mistake based on false assumptions.
If you want to store a date (not a timestamp) then use the column datatype DATE which lets you use:
DTCREATE DATE NOT NULL DEFAULT CURRENT DATE
How you choose, or future programmers choose , to render the value of a date on the SQL output is a different matter.
You may use BEFORE INSERT trigger to emulate a DEFAULT clause with such an unsupported function instead.
CREATE TRIGGER MYTAB_BIR
BEFORE INSERT ON MYTAB
REFERENCING NEW AS N
FOR EACH ROW
WHEN (N.DATE_CREATED IS NULL)
SET DATE_CREATED = VARCHAR_FORMAT(CURRENT_TIMESTAMP, 'YYYYMMDD');

Changing Jet SQL IsNull to to SQL IsNull Function

I have a query in MS Access that I am trying to change to SQL view
One of the select statement part is
IIf(IsNull([Book ID]),-1,[Book ID]) AS SubBookID
Unlike in Access T-SQL wants 2 parameters for the IsNull function.
What I need to do is something like
IIf(IsNull([Book ID],true),-1,[Book ID]) AS SubBookID
But we cannot use true like that cause T-SQL thinks that it is a column name
you are going to check if [Book ID] is null or not. If it is null then you are going to return -1 else you are going to return the [Book ID].
To achieve this you need to right it as:
ISNULL([Book ID],-1) AS SubBookID
As you see you do not need the IIF function anymore in this situation.
Read more about ISNULL in T-SQL: https://learn.microsoft.com/en-us/sql/t-sql/functions/isnull-transact-sql?view=sql-server-2017

Error catching a function error in TSQL

I am working with a SQL Server 2005 database table that is currently storing dates as varchars. This is outside of my control. For ease of reporting, I would like to create a view that converts these varchar dates to datetime fields.
The varchar dates are formatted for the most part, except for the occasional typing error.
DateString
----------
2001/01/02 -- most of the fields
2002/0601 -- typo, missing slash between month and day
2004/02/30 -- typo, no 30th of February
Because the dates are already formatted, I'm using the cast function to convert them to datetime.
cast(DateString as datetime)
The problem is when the cast function comes across an incorrect date, the query ends in error.
Is there are way to wrap just the function in a try...catch block? I see it is possible to wrap an entire query in a try...catch block, but the full query has multiple casts that must be done, and any combination could have typing errors.
I would use the built-in ISDATE() function. You can then write a CASE statement within your SELECT statement to either return the parsed date or either a null or some other result. Or, you can place it directly in the WHERE clause to only return those rows where there is a valid date.
A possible solution with the ISDATE() function in the SELECT list may look like:
select case
when ISDATE(DateString) = 1 then cast(DateString as datetime)
else null --or other error result
end as CastedDate
from TableName
If the logic is complicated (e.g. you want to try to correct the errors, such as missing slash, or nearest day in the case of 30th FEB), then one option is to create a user-defined function that contains the date parsing logic (string to date) logic in it, complete with error handling (e.g. scenario checking before casting). Then in the query, call the user defined function.
An outline:
CREATE FUNCTION udf_ParseDateString
(
#DateString nvarchar(20)
)
RETURNS DateTime
AS
BEGIN
DECLARE #returnDateTime datetime
-- Do any string checking, and date casting here
-- #DateString -> #returnDateTime
return #returnDateTime
END
Note that you won't be able to use TRY-CATCH in a UDF.
Alternatively, if your logic is simple, you could just use a cast inline, as suggested here.
SET DATEFORMAT ymd;
-- Incorporate this into query.
SELECT CASE WHEN ISDATE(#yourParameter) = 1
THEN CAST(#yourParameter AS DATETIME)
ELSE YourDefaultValue
END
If you were using SQL Server 2012, you could use the TRY_CAST function.

make a column in sybase default to the current date/time of row insertion

I have a sybase 15 DB and for one of my tables, I want to make a column default to the current date/time of the row insert. Is this possible?
In a sybase text, the following is said:
ALTER TABLE sales_order
MODIFY order_date DEFAULT CURRENT DATE
On my DB this doesn't do anything, as CURRENT DATE is not recognized.
using getDate() is a valid solution, you must have had a syntax error. Try it like this:
create table test_tbl (
date_data DATETIME default getDate() NOT NULL
)
Try using getDate() instead
... DEFAULT GETDATE() is correct. the case is irrelevant; mixed case may indicate a Java method, but it is a straight TSQL Function. Please post the exact error msg if you want further assistance.
Also, the ALTER TABLE method sets the Default for future INSERTS; if you want the existing data changed, you need to UPDATE (good for small tables) or unload/reload the table (demanded for the large).
Watch the NULL/NOT NULL: you do not want to change that without understanding. Again, the existing/future issue needs address. NOT NULL prevents NULL being explicitly passed as an INSERT VALUE.
CURRENT_DATE is a SQL standard that isn't universally adopted.
As noted elsewhere the getdate() T-SQL function should be used instead.

Stored Procedure vs User Defined Function for Error Handling

My ERP database uses non-nullable datetime fields. However, it enters '' for the datetime when one isn't available and returns ‘1900-01-01 00: 00: 00.000’ as the value.
I want to suppress the 1900 dates while stripping the Date only from the Datetime field. I created the following UDF to do that:
CREATE FUNCTION ExtractDate(#DirtyDate DATETIME)
RETURNS VARCHAR(10) AS
BEGIN
DECLARE #CleanDate VARCHAR(10)
SELECT #CleanDate =
CASE
WHEN #DirtyDate = '' THEN ''
ELSE CONVERT(VARCHAR(10), #DirtyDate, 101)
END
RETURN #CleanDate
END
This works, but I wanted to add error handling in case a user used it on something other than a datetime field. After some Googling, I found out that this isn't possible with UDF.
However, if I write this as a stored procedure, would I still be able to call it in a select statement? Can someone point me in the right direction?
No, you can't call a stored proc in a select statement.
I applaud your ambition in wanting to include error handling, but your best bet is to check for that on the app side - don't allow people to use the function on non-date fields.