SQL Formatting issue when converting varchar to date 103 - sql

I have a date field I pull in from excel as a varchar type and I currently convert it using this line:
convert(date,[Appt Date],103) as [Appt date]
this works but the result is a date in the following format:
YYYY/MM/DD
According to other sites the 103 format at the end of the line should convert this varchar to UK formatting ( DD/MM/YYYY ).
Can anyone advise why this is not happening?

By default, MSSQL server store dates in YYYY/MM/DD. You can only change the language on the whole server, not individual databases.
set language 'british english'
run this first before inserting.
or another alternative is to use SET DATEFORMAT (from MSDN)
declare #dates table (orig varchar(50) ,parsed datetime)
SET DATEFORMAT ydm;
insert into #dates
select '2008-09-01','2008-09-01'
SET DATEFORMAT ymd;
insert into #dates
select '2008-09-01','2008-09-01'
select * from #dates
It should be VARCHAR not DATE
SELECT convert(VARCHAR(20),[Appt Date],103) as [Appt date]

Related

VARCHAR as 09:20:00 Jan 30, 2013 PST. Covert Varchar to date in SQL

How to convert varchar datetime value returned from paypal to Datetime in C#..
Below is the query I want to get the data which was not supported because of varchar datatype..
select *
from table1
where Month(date) = '05'
and Year(date) = '2021'
Here the date column's datatype is varchar as sample value (09:20:00 Jan 30, 2013 PST).
Can anyone help me to convert this varchar to datetime or date in SQL Server?
As I mentioned the problem is your design here. You are storing date and time values as a varchar; a grave mistake. Fix your design fix the problem. Assuming that all your values are in the format hh:mm:ss MMM dd, yyyy tz, and the time zone is significant, you could do something like this:
ALTER TABLE dbo.YourTable ADD NewDate datetimeoffset(0);
GO
CREATE TABLE #TimeZones (Timezone varchar(4),
Offset varchar(6));
--You need to create the rest of the timezones, these are examples
INSERT INTO #TimeZones
VALUES('PST','-08:00'),
('PDT','-07:00'),
('GMT','+00:00'),
('BST','+01:00'),
('CET','+01:00'),
('CEST','+02:00');
GO
UPDATE YT
SET NewDate = TRY_CONVERT(datetimeoffset(0),CONCAT(S.FormattedDateString,TZ.Offset))
FROM dbo.YourTable YT
CROSS APPLY (VALUES(REPLACE(SUBSTRING(YT.[date],10,13) + LEFT(YT.[date],9),',',''),(RIGHT(YT.[date],CHARINDEX(' ',REVERSE(YT.[date]))-1))))S(FormattedDateString,TimeZone)
JOIN #TimeZones TZ ON S.TimeZone = TZ.TimeZone;
GO
DROP TABLE #Timezones;
GO
EXEC sys.sp_rename N'dbo.YourTable.Date',N'OldStringDate','COLUMN';
GO
EXEC sys.sp_rename N'dbo.YourTable.NewDate',N'Date','COLUMN';
GO
The original values will then be in OldStringDate so you can get a list of values that didn't convert with the following:
SELECT OldStringDate
FROM dbo.YourTable
WHERE OldStringDate IS NOT NULL
AND [Date] IS NULL;
Then you can trivially get the data from your table with the following:
SELECT *
FROM dbo.YourTable
WHERE [Date] >= '2021-05-01T00:00:00-08:00'
AND [Date] < '2021-06-01T00:00:00-08:00';

UPDATE SET FORMAT not working in SQL Server 2016?

FORMAT instruction works in a SELECT but has no effect in an UPDATE:
SELECT ##VERSION
DROP TABLE IF EXISTS #t;
CREATE TABLE #t(DateMin datetime);
INSERT INTO #t VALUES ('2019-13-01 00:00:00')
SELECT * FROM #t
UPDATE #t SET DateMin = FORMAT(DateMin, 'dd/MM/yyyy');
SELECT * FROM #t;
SELECT #DateMin AS a, FORMAT(#DateMin, 'dd/MM/yyyy') AS b
A type like DATETIME isn't stored with a format.
So if one updates a DATETIME with a string in a certain format, it doesn't matter for the stored value in the DATETIME field.
The formatted string is implicitly converted to a datetime. At least if it's in a format that's valid.
The function FORMAT, which returns a NVARCHAR is rather used for representation of the datetime field in a query.
Or if one wants to INSERT/UPDATE a string field with a datetime in a certain format. But that should be avoided, because it's much easier to work with a datetime than a string.
If you want to change that format for the user use this:
set dateformat dmy;
By running this statement:
DBCC USEROPTIONS;
you will see your dateformat is ydm so you can alway back it up to that if this is not what you wanted :)
You cannot set the output format of a datetime in the datetime itselfs.
If you need to output the datetime as formatted char/varchar, you need to use the convert-function when you select the data:
SELECT CONVERT(char(10), CURRENT_TIMESTAMP, 101) -- format: MM/dd/yyyy
SELECT CONVERT(char(10), CURRENT_TIMESTAMP, 103) -- format: dd/MM/yyyy
In your case:
SELECT #DateMin AS a, CONVERT(char(10), #DateMin, 103) AS b
That works as expected.
If you want to have a mutable data-type, you need to declare it as sql_variant:
DROP TABLE IF EXISTS #t;
CREATE TABLE #t(DateMin sql_variant);
INSERT INTO #t VALUES ('2019-01-13T00:00:00')
UPDATE #t SET DateMin = FORMAT(CAST(DateMin AS datetime), 'dd''/''MM''/''yyyy');
SELECT * FROM #t;
Also, your format-expression needs to explicitly put the / into quotation marks, aka 'dd''/''MM''/''yyyy', otherwise sql-server replaces it with the date-separator specific to the current culture, which would be . in my case.
Just use convert with option 103 instead, it works on all versions of sql-server and it's probably faster.
Also, your insert-statement fails on some versions of sql-server, because iso-date-format is 2019-01-13T00:00:00 and not 2019-13-01 00:00:00
Correct is:
INSERT INTO #t VALUES ('2019-01-13T00:00:00')
Also
DROP TABLE IF EXISTS #t;
is sql-server 2016+ only, otherwise you need
IF OBJECT_ID('tempdb..#t') IS NOT NULL DROP TABLE #t
And post sql-server 2005, you should use datetime2 instead of datetime.
You shouldn't use datetime anymore, because datetime uses float, and as such is imprecise - if you insert an iso datetime value, it can do funny things because of the float-point-machine-epsilon, e.g. set it to the next day if you have 23:59:59.999, just as a scary example.
I advise you to never use the sql_variant type. If you have a temp-table with defined columns, just create another column where you will write the char/varchar value to.

SQL Server: best way to insert "mm/dd/yyyy" into a "date" or "datatime2" column?

I have a bunch of values in the form of mm/dd/yyyy stored in a CSV. An example is 06/26/2017. What I found was that I could NOT insert it into a column declared as date or datetime2 type. What I CAN do is to modify that (empty) column to varchar first, then insert.
However at this point, after insertion as varchars, how can I convert this column to "date" or "datatime2"?
Attempting to set system-wide format doesn't work:
sql> SET DATEFORMAT 'mm/dd/yyyy'
[2019-03-31 09:42:04] [S0001][2741] SET DATEFORMAT date order 'mm/dd/yyyy' is invalid.
If the column's data type is date then convert the string to date with:
convert(date, '03/31/2019', 101)
and then insert it.
See the demo.
Read more about convert()
Edit:
Create a varchar column and a date column. Insert the values inside the varchar column and when the process finishes, update the date column by converting each value to a date, like:
UPDATE tablename
SET datecolumn = convert(date, varcharcolumn, 101)
After that you can remove the varchar column.

Executing the stored procedure causes error

I have a stored procedure in which I want to get the reportdate while executing.
I pass one parameter to the stored procedure for executing it,. I pass it like this
exec UserReportData '10-06-2016'
but I get an error:
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
This is my stored procedure:
ALTER PROCEDURE [dbo].[UserReportData]
#As_ONDATE Datetime
AS
BEGIN
DECLARE #REPORTDATE datetime
--DECLARE #OPENING INT
SELECT *
INTO #temptable
FROM
(SELECT
a.CUser_id, b.User_Id, a.U_datetime AS REPORTDATE
FROM
inward_doc_tracking_trl a, user_mst b
WHERE
a.CUser_id = b.mkey
AND CONVERT(varchar(50), a.U_datetime, 103) = #As_ONDATE) AS x
DECLARE Cur_1 CURSOR FOR
SELECT CUser_id, User_Id
FROM #temptable
OPEN Cur_1
DECLARE #CUser_id INT
DECLARE #User_Id INT
FETCH NEXT FROM Cur_1 INTO #CUser_id, #User_Id
WHILE (##FETCH_STATUS = 0)
BEGIN
SELECT CONVERT(varchar(50), U_datetime, 103)
FROM inward_doc_tracking_trl
WHERE CONVERT(varchar(50), U_datetime, 103) = #As_ONDATE
UPDATE #temptable
SET REPORTDATE = #REPORTDATE
WHERE CUser_id = #CUser_id
AND User_Id = #User_Id
FETCH NEXT FROM Cur_1 INTO #CUser_id, #User_Id
END
CLOSE Cur_1
DEALLOCATE Cur_1
SELECT * FROM #temptable
DROP TABLE #temptable
END
Kindly help me know what is the cause of the error.
The various settings (language, date format) only influence how the DateTime is shown to you in SQL Server Management Studio - or how it is parsed when you attempt to convert a string to a DateTime.
There are many formats supported by SQL Server - see the MSDN Books Online on CAST and CONVERT. Most of those formats are dependent on what settings you have - therefore, these settings might work some times - and sometimes not.
The way to solve this is to use the (slightly adapted) ISO-8601 date format that is supported by SQL Server - this format works always - regardless of your SQL Server language and dateformat settings.
The ISO-8601 format is supported by SQL Server comes in two flavors:
YYYYMMDD for just dates (no time portion); note here: no dashes!, that's very important! YYYY-MM-DD is NOT independent of the dateformat settings in your SQL Server and will NOT work in all situations!
or:
YYYY-MM-DDTHH:MM:SS for dates and times - note here: this format has dashes (but they can be omitted), and a fixed T as delimiter between the date and time portion of your DATETIME.
This is valid for SQL Server 2000 and newer.
If you use SQL Server 2008 or newer and the DATE datatype (only DATE - not DATETIME!), then you can indeed also use the YYYY-MM-DD format and that will work, too, with any settings in your SQL Server.
Don't ask me why this whole topic is so tricky and somewhat confusing - that's just the way it is. But with the YYYYMMDD format, you should be fine for any version of SQL Server and for any language and dateformat setting in your SQL Server.
The recommendation for SQL Server 2008 and newer is to use DATE if you only need the date portion, and DATETIME2(n) when you need both date and time. You should try to start phasing out the DATETIME datatype if ever possible
So in your concrete case - just change how you call your stored procedure to:
exec UserReportData '20160610' -- 10th of June, 2016
or
exec UserReportData '20161006' -- 6th of October, 2016
depending on whether this was the 6th October or the 10th June of 2016 you're interested in ...
You are passing datetime, by default SQL Server uses MMDDYYYY or YYYYMMDD format.
You are using the DD-MM-YYYY format,
Either you write as
set dateformat dmy --set ddmmyyyy format
exec UserReportData '10-06-2016'
set dateformat mdy --set default again
or you passed the value which is in proper format. No other solution work.

Convert date string to date sql server

I have a table tbl with column cln varchar(50).
Data is stored in format 'January-2008', February-2009, March-2010 etc(full month name)
I want to convert it to date (for comparison, sort etc).
please try below query
DECLARE #v varchar(20)
SET #v='January-2008'
SELECT CAST('01-'+#V as DATE)
Since you don't get the day data and only -, we'll add '01-' to complete the date day part.
sql fiddle link: http://sqlfiddle.com/#!6/6f326/7
Use Convert with Style to avoid errors in different date settings
DECLARE #v varchar(20)
SET #v='January-2008'
SELECT CONVERT(DATETIME,'01-'+#v,13)