how to retrieve the records based on the GETDATE - sql-server

I am trying to automate the task using SQL server agent to generate the report of the people who gets inserted to the table on regular basis. I have created the below stored procedure, and was trying to use same query in SQL server agent job but is not working can someone please help.
SELECT s.LAST_NAME AS sn,
RTRIM(s.FIRST_NAME)+ ' ' + LTRIM(s.LAST_NAME) AS Name,
s.FIRST_NAME AS F_Name
LEFT(middle_name,1) AS Initial,
sy.USERNAME AS USER,
s.HOME_ZIP AS ZIP,
RTRIM(UPPER(sy.USERNAME)) + LTRIM('#xyz.com') AS userP,
stm.DESCRIPTION_Maj AS company,
rg.RECORD_INPUT_DATE
FROM STCIO s
JOIN SYSME sy
ON s.ID_NUMBER =sy.ID_NUMBER
JOIN EHMGR rg
ON s.ID_NUMBER =rg.ID_NUMBER
JOIN STMEER stm
ON rg.MAJOR =stm.MAJOR
AND s.MAT_CODE IN ('','G','Q')
AND rg.CURRENT_FLAG = 'X'
AND CONVERT(datetime,CONVERT(CHAR(8),rg.RECORD_INPUT_DATE)) = GETDATE()
NOTE:datatype for Record_input_date is numeric(8,0)
Error message received is
"Arithmetic overflow error converting expression to data type datetime."
I don't have an authority to make any changes. All I'm looking for is to have this query running converting the record_input_date (numeric) to datetime and populate the record based on the getdate()

Now this would happen if you still have the date stored as numeric in a wrong format (non ANSI format)
Like instead of 20160307 for today's date it stores it as 20160703 in which case it will give error for values like 20162002 or when the date is stored as ddmmyyyy or any other variant format. To solve look at some sample data and tweak your query from
CONVERT(datetime,convert(char(8),rg.RECORD_INPUT_DATE)) = GETDATE()
to
CONVERT(datetime,convert(char(8),rg.RECORD_INPUT_DATE),<formatstring>) = GETDATE()
See list of format strings here
Another way is to use date from parts function in higher version of sql server like
SELECT DATEFROMPARTS(RECORD_INPUT_DATE / 10000,
RECORD_INPUT_DATE % 100,
(RECORD_INPUT_DATE/ 100) % 100) AS YR_MNTH_DT
If you cannot use either of above, you'll have to isolate days,months and year from the number.
Example if your number is wrong format like ddmmyyyy (03062016)
DECLARE #dd INT, #mm INT, #yyyy INT, #newdate INT
SET #dd= RECORD_INPUT_DATE/1000000 --3
SET #mm= (RECORD_INPUT_DATE/10000) %100--6
SET #yyyy= (RECORD_INPUT_DATE) % 10000--2016
SET #newdate= #yyyy*10000+#mm*100+#dd
and use this #newdate for comparison
CONVERT(datetime,convert(char(8),#newdate)) = GETDATE()

Step 1 is turning this wall of text query into something you can read.
SELECT s.LAST_NAME AS sn
, RTRIM(s.FIRST_NAME) + ' ' + LTRIM(s.LAST_NAME) AS Name
, s.FIRST_NAME AS F_Name
, LEFT(middle_name, 1)AS Initial
, sy.USERNAME AS [USER]
, s.HOME_ZIP AS ZIP
, RTRIM(UPPER(sy.USERNAME)) + '#xyz.com' AS userP
, stm.DESCRIPTION_Maj AS company
, rg.RECORD_INPUT_DATE
FROM STCIO s
JOIN SYSME sy ON s.ID_NUMBER = sy.ID_NUMBER
JOIN EHMGR rg ON s.ID_NUMBER = rg.ID_NUMBER
JOIN STMEER stm ON rg.MAJOR = stm.MAJOR
AND s.MAT_CODE in ('', 'G', 'Q')
AND rg.CURRENT_FLAG = 'X'
AND CONVERT(DATETIME, CONVERT(CHAR(8), rg.RECORD_INPUT_DATE)) = GETDATE()
The problem here is that you have an integer that is not able to be converted to a datetime value. This is an inherent problem of using improper datatypes. You are likely going to be forced to drop the date condition from this query and replace it with an ISDATE. Insert those results to a temp table. Then another query to pull from the temp table with your date predicates.

Related

Trouble casting string to date

I keep getting the following error when running my query and am having trouble finding a solution.
Conversion failed when converting date and/or time from character string.
select * from creditcard
where cast(left(expdate,2) + '/01/' + right(expdate,2) as date) < '08/01/17'
and paycode <> ''
All of the dates in the table look like this '07/17'
declare #myfakedate varchar(25) = '07/17'
declare #mydatestr varchar(25)
Select #mydatestr = stuff(#myfakedate,3,0,'/01')
select #mydatestr
will give you '07/01/17'
If 2012+ user try_convert() just in case you have bogus data. Otherwise, the standard convert() should do
Example
Select *
From YourTable
Where try_convert(date,replace(expdate,'/','/01/'))<'08/01/17'

Conversion failed when converting date and/or time from character string - SQL Server error

I'm trying to dynamically select tables from my database based on the table name, which in turn is based on the date of creation.
For example, the tables might be called 'tableA20110305', or 'tableB20110305', indicating that the tables were created on 05 March 2011.
I'm trying to write a query that will select all tables named thus, created before a certain cutoff date (1 year ago), and concatenate them into DROP TABLE command statements in a table variable. The select statement looks like this.
DECLARE #cutoffDate datetime = CONVERT(DATETIME, DATEADD(YEAR,-1,GETDATE()), 112)
SELECT 'DROP TABLE "' + TABLE_NAME + '"' AS 'Command'
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_NAME LIKE 'tableA%' OR TABLE_NAME LIKE 'tableB%')
AND (CONVERT(DATETIME, SUBSTRING(TABLE_NAME, 7, 8), 112) < #cutoffDate)
ORDER BY Command DESC
However, when I execute this SQL, I'm seeing the following error:
Msg 241, Level 16, State 1, Line 14
Conversion failed when converting date and/or time from character string.
BUT... if I execute the following SQL statement, I see no error and get date returned as expected:
SELECT CONVERT(DATETIME, SUBSTRING('tableA20110305', 7, 8), 112)
I don't understand why these queries are not returning the same result or where this error is coming from.
I'd very much appreciate any insights..
This explains this behavior very well. Taken from 70-461: Querying Microsoft SQL Server 2012:
WHERE propertytype = 'INT' AND CAST(propertyval AS INT) > 10
Suppose
that the table being queried holds different property values. The
propertytype column represents the type of the property (an INT, a
DATE, and so on), and the propertyval column holds the value in a
character string. When propertytype is 'INT', the value in propertyval
is convertible to INT; otherwise, not necessarily.
Some assume that
unless precedence rules dictate otherwise, predicates will be
evaluated from left to right, and that short circuiting will take
place when possible. In other words, if the first predicate
propertytype = 'INT' evaluates to false, SQL Server won’t evaluate the
second predicate CAST(propertyval AS INT) > 10 because the result is
already known. Based on this assumption, the expectation is that the
query should never fail trying to convert something that isn’t
convertible.
The reality, though, is different. SQL Server does
internally support a short-circuit concept; however, due to the
all-at-once concept in the language, it is not necessarily going to
evaluate the expressions in left-to-right order. It could decide,
based on cost-related reasons, to start with the second expression,
and then if the second expression evaluates to true, to evaluate the
first expression as well. This means that if there are rows in the
table where propertytype is different than 'INT', and in those rows
propertyval isn’t convertible to INT, the query can fail due to a
conversion error.
And in your case engine decides first to do filter by dates part and it fails.
And there can be several workaround:
Use TRY_CAST instead(supported from SQL Server 2012)
First select all tables which are like 'tableA%' OR TABLE_NAME LIKE 'tableB%' into some temp table and then do another filter (CONVERT(DATETIME, SUBSTRING(TABLE_NAME, 7, 8), 112) < #cutoffDate)
Well , as mentioned in the comments you probably have other tables in your database that does not follow the same format as tableA<DateFormat> , so you need to try to filter only them .
You can use ISDATE combined with CASE EXPRESSION to make sure the SUBSTRING is indeed in a date format:
DECLARE #cutoffDate datetime = CONVERT(DATETIME, DATEADD(YEAR,-1,GETDATE()), 112)
SELECT 'DROP TABLE "' + TABLE_NAME + '"' AS 'Command'
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_NAME LIKE 'tableA%' OR TABLE_NAME LIKE 'tableB%')
AND CASE WHEN ISDATE(SUBSTRING(TABLE_NAME, 7, 8)) = 1
THEN (CONVERT(DATETIME, SUBSTRING(TABLE_NAME, 7, 8), 112)
ELSE getdate()
END < #cutoffDate
ORDER BY Command DESC
DECLARE #cutoffDate Varchar(8); --<-- use varchar here not datetime since you YYYYMMDD
SET #cutoffDate = CONVERT(Varchar(8), DATEADD(YEAR,-1,GETDATE()), 112)
SELECT 'DROP TABLE '+ QUOTENAME(TABLE_SCHEMA) +'.' + QUOTENAME(TABLE_NAME) AS [Command]
From (
Select TABLE_SCHEMA , TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_NAME LIKE 'tableA%' OR TABLE_NAME LIKE 'tableB%')
AND ISDATE(SUBSTRING(TABLE_NAME, 7, 8)) = 1
) A
Where (CONVERT(DATETIME, SUBSTRING(TABLE_NAME, 7, 8)) < #cutoffDate)
ORDER BY Command DESC
Adding ISDATE(SUBSTRING(TABLE_NAME, 7, 8)) = 1 to your where clause will only bring back the results which has a proper date value in its name hence converting it to date/datetime should work.
The problem is that some table matches the condition but does not have the prescribed format. In SQL Server 2012+, you can use try_convert():
SELECT 'DROP TABLE "' + TABLE_NAME + '"' AS 'Command'
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_NAME LIKE 'tableA%' OR TABLE_NAME LIKE 'tableB%') AND
(TRY_CONVERT(DATETIME, SUBSTRING(TABLE_NAME, 7, 8), 112) < #cutoffDate)
ORDER BY Command DESC;
In earlier versions, you might as well use string comparisons:
SELECT 'DROP TABLE "' + TABLE_NAME + '"' AS 'Command'
FROM INFORMATION_SCHEMA.TABLES
WHERE (TABLE_NAME LIKE 'tableA%' OR TABLE_NAME LIKE 'tableB%') AND
(SUBSTRING(TABLE_NAME, 7, 8), 112) < CONVERT(VARCHAR(8), #cutoffDate, 112))
ORDER BY Command DESC;
This converts the cutoff date to a string in the format of YYYYMMDD, which is fine for this comparison. However, you do need to be careful about the values that do not match the specific format -- this might accidentally delete a table that you don't intend to delete.

Get data after year 2012 SQL Server

I am trying to get data after year 2012.
Date is saved in nvarchar format in a table. For example: 12/31/2010
Column also has some other values like 'Confidential', I don't want this row.
I am trying a query (shown below) but it is not succeed :-
select *
from tbl_ProductionWells
where CONVERT(NVARCHAR(10), wellstatusdate, 103) > CONVERT(NVARCHAR(10), '01/01/2012', 103)
Edited :-
I tried this :-
SELECT *
FROM tbl_ProductionWells
WHERE DATEPART(YEAR, CAST(wellstatusdate AS date)) > 2012
But it is giving an error (shown below), This column also has some text values like 'not available','Confidential' .. :-
Msg 241, Level 16, State 1, Line 1
Conversion failed when converting date and/or time from character string.
Note:- I can't change column datatype as it also contains some other texts.
Thanks in advance
First of all: Store date values in DATE columns, datetimes in DATETIME2 columns. Always choose proper data type for your data
You have to convert your NVARCHAR to DATE, then compare it to 2012-01-01
OR you can extract the 'year' part of your string.
SELECT *
FROM tbl_ProductionWells
WHERE CONVERT(DATE, wellstatusdate) >= '2012-01-01'
The best choice is to change your column's data type to DATE. After that, you can do lots of magicial things with those values. Store the 'Confidental' flag in another column.
EDIT
Some additional info:
Please note, that the STRING -> DATE conversion depends on the current session's language.
Run this batch to see the difference:
DECLARE #DateAsChar VARCHAR(32) = '01/02/12';
SET LANGUAGE us_english
SELECT CONVERT(VARCHAR(32), CONVERT(DATE, #DateAsChar), 120)
SET LANGUAGE Hungarian
SELECT CONVERT(VARCHAR(32), CONVERT(DATE, #DateAsChar), 120)
SET LANGUAGE Deutsch
SELECT CONVERT(VARCHAR(32), CONVERT(DATE, #DateAsChar), 120)
How about:
WITH cte
AS ( SELECT *
FROM tbl_ProductionWells
WHERE ISDATE(wellstatusdate) = 1
)
SELECT *
FROM cte
WHERE DATEPART(YEAR, CAST(wellstatusdate AS DATE)) > 2012
Select all data from the table that is a date using IsDate, then work with that dataset only.
SELECT * FROM
(SELECT * FROM tbl_ProductionWells WHERE ISDATE(wellstatusdate) = 1)
WHERE CAST(wellstatusdate as Date) > #YOURDATE

How do I deserialise an xml string in SQL Server into multiple columns?

I am trying to deserialize xml in a SQL Server stored procedure before bringing it into c# win forms. My current result table looks as follows:
Edit: As the table above is too small to read below is an example of
what it contains:
Column 1 is just a time 07:00, 07:09, etc.
Column 2 contains the following data:
Row 1:
ABADILLA ARIEL<RegistrationId>29</RegistrationId>, BLAKE LORCAN<RegistrationId>30</RegistrationId>, CRONIN SHANE<RegistrationId>31</RegistrationId>
Row 2:
ADAMS NORMAN<RegistrationId>33</RegistrationId>, ADAMS WILLIAM<RegistrationId>34</RegistrationId>, AHEARNE PAUL<RegistrationId>35</RegistrationId>, LAWLOR DES<RegistrationId>32</RegistrationId>
So each row can have up to but no more than 4 entries.
End edit
I would like to be able to do a few things to this with this table, primarily I need to be able to modify it into the following format:
But ultimately i'd like to display the information with the name only but maintaining the link to the registration number without actually displaying it. This part might be easier to do in c# win forms though so I think i'd be happy enough if I could get it into the format shown above.
My sql code to date to return the results table shown initialls is as follows:
DECLARE #Registered TABLE
(CompetitionName VARCHAR(50),
CompetitionDate Date,
StartTime TIME,
RegistrationId INTEGER,
PlayersName Varchar(60)
)
INSERT INTO #Registered
SELECT MAX(c.CompetitionName) AS 'Competition Name', MAX(c.[Date]) AS 'Competition Date',
CONVERT(VARCHAR, r.PlayersStartTime, 108) AS 'Start Time', MAX(r.RegistrationId) AS RegistrationId,
CASE WHEN m.MemberId IS NOT NULL THEN (m.Surname + ' ' + m.FirstName) ELSE (nm.Surname + ' '+ nm.Firstname) END AS PlayersName
FROM dbo.Competitions c
LEFT JOIN [dbo].[Registration] r ON c.[CompetitionId] = r.[CompetitionId]
LEFT JOIN dbo.Members m ON r.MemberId = m.MemberId
LEFT JOIN dbo.NonMembers nm ON r.NonMemberId = nm.NonMemberId
WHERE [Date] = '20130104'
AND c.CompetitionId = 10
GROUP BY r.PlayersStartTime, m.MemberId, m.FirstName, m.Surname, nm.FirstName, nm.Surname
----
SELECT DISTINCT Main.StartTime,
STUFF((SELECT ', ' + PlayersName, + RegistrationId
FROM #Registered list
WHERE list.StartTime = Main.StartTime
FOR XML PATH ('')),1,2,''
) AS PlayerList
FROM #Registered Main;

Validate Date Values in NVarchar field

Hi I have a reporting application written against some 3rd party software. Unfortunately it stores all values as nvarchar and does not validate data entry on the client side as a result I am getting the following error when
"Conversion failed when converting date and/or time from character string"
System.Data.SqlClient.SqlException was unhandled by user code
or if I try to execute the code in SSMS:
Msg 241, Level 16, State 1, Procedure settlement_list, Line 10
Conversion failed when converting date and/or time from character string.
I assume this is the result of someone entering a text value in the data field so I've tried this ISDATE code to find the bad value:
SELECT mat3_02_01, CONVERT(datetime, mat3_04_02), mat3_04_02 FROM lntmu11.matter3
WHERE ISDATE(mat3_04_02) <> 1
AND Coalesce(mat3_04_02, '') <> ''
order by mat3_04_02 desc
and I get zero row returned ... I also manually sifted through the data (its sveral 100 thousand rows so its kind of hard and see no bad values ???
Does anyone have any suggestions ?
EDIT ---
Here is the stored proc (I know where clause is ugly)
SELECT mat_no, 'index'=matter.mat1_01_06,
'insurance'=Replace(Replace(matter.mat1_03_01, 'INSURANCE COMPANY', ' '), 'COMPANY', ''),
matter.[status], 'casestage'=mat1_04_01, 'injured'=matter.MAT1_01_07, matter.client,
'terms'=mat3_04_06, 'ClmAmt'=matter.mat1_07_01,
'ClmBal'=matter.mat1_07_03, 'SetTot'=matter3.MAT3_04_09, 'By'=mat3_03_02,
'DtSttld'=mat3_04_02, 'SettlStg'=(MAT3_06_08 + ' / ' + MAT3_06_05)
FROM [lntmu11].matter3 inner join
[lntmu11].matter ON [lntmu11].matter.sysid = [lntmu11].matter3.sysid
WHERE
(DateDiff(month, convert(datetime, MAT3_04_02, 101), GETDATE()) = #range
and mat3_03_02 like #by)
or
(mat3_04_06 like #by2
and DateDiff(month, convert(datetime, MAT3_04_02, 101), GETDATE()) = #range)
ORDER BY MAT3_03_02
You can't force the order the query engine will try to process the statement without first dumping the ISDATE() = 1 rows into a #temp table. You can't guarantee the processing order or short circuiting, even though some will suggest using a CTE or subquery to filter out the bad rows first. So some might suggest:
;WITH x AS
(
SELECT mat3_02_01, mat3_04_02
FROM Intmu11.matter3
WHERE ISDATE(mat3_04_02) = 1
AND mat3_04_02 IS NOT NULL -- edited!
)
SELECT mat3_02_01, CONVERT(DATETIME, mat3_04_02), mat3_04_02
FROM x
ORDER BY mat3_04_02 DESC;
And this may even appear to work, today. But in the long term, really the only way to guarantee this processing order - in current versions of SQL Server - is:
SELECT mat3_02_01, mat3_04_02
INTO #x
FROM Intmu11.matter3
WHERE ISDATE(mat3_04_02) = 1
AND mat3_04_02 IS NOT NULL; -- edited!
SELECT mat3_02_01, CONVERT(DATETIME, mat3_04_02), mat3_04_02
FROM #x
ORDER BY mat3_04_02 DESC;
Have you thought about validating the values on input? For example, you can change where this error appears in the application by slapping them on the wrist when they enter an invalid date, instead of punishing the person who selects their bad data. If you are controlling the update/insert via a stored procedure, you can say:
IF ISDATE(#mat3_04_02) = 0
BEGIN
RAISERROR('Please enter a valid date.', 11, 1);
RETURN;
END
If you aren't controlling data manipulation via stored procedure(s), then you can add a check constraint to the table (after you've cleaned up the existing bad data).
UPDATE Intmu11.matter3 SET mat3_04_02 = NULL
WHERE ISDATE(mat3_04_02) = 0;
ALTER TABLE Intmu11 WITH NOCHECK
ADD CONSTRAINT mat3_04_02_valid_date CHECK (ISDATE(mat3_04_02)=1);
This way when the error message gets bubbled up to the user they will see the constraint name and hopefully will be able to map that to the data entry point on the front end that failed:
Msg 547, Level 16, State 0, Line 1 The INSERT statement conflicted
with the CHECK constraint "mat3_04_02_valid_date". The conflict
occurred in database "your_db", table "Intmu11.matter3", column
'mat3_04_02'. The statement has been terminated.
Or better yet, use the right data type in the first place! Again, after updating the existing bad data to be NULL, you can say:
ALTER TABLE Intmu11.matter3 ALTER COLUMN mat3_04_02 DATETIME;
Now when someone tries to enter a non-date, they'll get the same error that the users are currently getting when they try to select the bad data:
Msg 241, Level 16, State 1, Line 1 Conversion failed when
converting date and/or time from character string.
In SQL Server 2012, you'll be able to get around this with TRY_CONVERT() but you should still be trying to get the data type right from the beginning.
Examine the query where
ISDATE(mat3_04_02) = 1
AND
Coalesce(mat3_04_02, '') = ''
To be a date it must have a value.
But is only matches the second condition if it has not value.
The intersection (and) of those two conditions is always false.
If you are looking for null then "mat3_04_02 is null" but it still will return 0 rows.
Try
SELECT mat3_02_01, CONVERT(datetime, mat3_04_02), mat3_04_02
FROM lntmu11.matter3
WHERE ISDATE(mat3_04_02) = 1
order by CONVERT(datetime, mat3_04_02) desc
I think you would want date sorted and not string sorted
The question started as finding valid dates and it morphed into finding invalid dates
SELECT mat3_02_01, mat3_04_02
FROM lntmu11.matter3
WHERE ISDATE(mat3_04_02) = 0
AND mat3_04_02 is not null
order by mat3_04_02) desc

Resources