Common SQL to compare dates in SQL Server and ORACLE - sql

I need to include a date comparison in my query where I compare a date string to a DATETIME column but i need it to work on both ORACLE and SQL Server and not have two separate queries.
Are there any date comparissons which will work on both oracle and sql?
ORACLE:
Select * from MyTable where myDate > DATE '2013-04-10'
SQL Server:
Select * from MyTable where myDate > convert(DATETIME,'2013-04-10', 126)

This portability issue only applies with literals.
I do not believe there is a fully portable way to do this because SQL Server does not support the ANSI literal DATE keyword and all the CAST, CONVERT, TO_DATE, and date functions are not identical on all platforms.
Note that your second query can also be written as Select * from MyTable where myDate > '20130410'.
It would be nice if there was support in SQL Server for the ANSI DATE literal feature (DB/2 and Teradata both have this).
I could not find a Connect item on this, nor anything about why SQL Server doesn't support the ANSI DATE, TIME and TIMESTAMP literal keywords.
I'm wondering in your scenario, whether it would be possible to use a parameter instead?
The solution in Jack's comment Common SQL to compare dates in SQL Server and ORACLE will make this code portable, but you will have to have a non-portable scalar function. This might be a viable option for you - note that in SQL Server, you will need to prefix a scalar function with its schema - this might introduce another wrinkle between the Oracle code and SQL code if you can't make the schemas the same name (note in Oracle, the prefix could be the name of a package instead of a schema if you put the function inside a package)

Is defining your own user-defined functions allowed? You could create a function which abstracts the DBMS specific code and returns a literal 'True' or 'False' result.
[MSSQL User Defined Functions: ]http://msdn.microsoft.com/en-ca/library/ms186755.aspx
[Oracle User Defined Functions]http://ocs.oracle.com/cd/B19306_01/server.102/b14200
Oracle apparently does not allow user defined functions to return a Boolean type, so a string (or numeric) result is required.

Related

SQLite - TZ format to Date time only using SQL queries

I have a SQLite database with a simple table in the format of:
ID,DateText,Name
1,2020-09-01T18:57:17Z,John
2,2022-12-01T04:00:09Z,Laurel
...
The DateText column is declared as TEXT on the "create table" statement. Using only SQL, I need to:
Create a new column with the DateText data.
Obtain the "oldest" date
Obtain the "newest" date
Note that I need to resolve this with a SQL query. I cannot read into a programming language, parse, and update table--I need to do everything on SQL. For example, SQL Server DateTime with timezone is the opposite, but they are using node.js, something I cannot do.
You can get the oldest and newest using min() and max():
SELECT ID, min(DateTime), Name FROM YourTable; -- Oldest
SELECT ID, max(DateTime), Name FROM YourTable; -- Newest
The nice thing about ISO-8601 date and time format strings is that they sort lexicographically without having to do anything special with them.
These queries would give an error on most SQL database engines because of the mix of non-grouped columns with an aggregate function, but SQLite explicitly will return the row that goes with the minimum or maximum column value. And of course if you don't want the other columns, just leave them out of the SELECT.

Add a day to a date in Postgres and SQL Server

I'm looking to find a way to add a day to a date in both Postgres and SQL Server so I don't have to add an if condition checking which database the server is running
DATEADD(day, 1, STOP_DATE)
doesn't work in PostgreSQL &
STOP_DATE + 1
doesnt work in sql server
Overall, it is not a good idea to try to write SQL code using syntax that is common on both SQL Server and Postgres. You are severely limiting yourself and will sooner or later come across a query that runs too slowly because it doesn't use syntax specific to one of the DBMS.
For example, with your approach you are artificially refusing to use lateral joins, because their syntax is different in Postgres (LATERAL JOIN) and SQL Server (CROSS/OUTER APPLY).
Back to your question.
You can add an integer value to a date value in Postgres and to datetime value in SQL Server.
SQL Server
CREATE TABLE T(d datetime);
INSERT INTO T VALUES ('2020-01-01');
SELECT
d, d+1 AS NextDay
FROM T
http://sqlfiddle.com/#!18/d519d9/1
This will not work with date or datetime2 data types in SQL Server, only datetime.
Postgres
CREATE TABLE T(d date);
INSERT INTO T VALUES ('2020-01-01');
SELECT
d, d+1 AS NextDay
FROM T
http://sqlfiddle.com/#!17/b9670/2
I don't know if it will work with other data types.
Define a function in PostgreSQL that works like the sql server function.
Edit:
can't pass day
Create a function with the same name on each database system that adds a day accordingly.

Error in MS SQl 11.0 given code: 'unix_timestamp' is not a recognized built-in function name

I got the SQL query from another developer and there was unix_timestamp function, because this query returns a list of objects from database in the exact period of time. Query doesn't work because of the SQL error 195: 'unix_timestamp' is not a recognized built-in function.
n.created>unix_timestamp('2019-02-28') and n.created<unix_timestamp('2019-09-01')
"unix_timestamp" is a built in function on MySQL - it isn't on SQLserver.
Here's the code to get the unix timestamp now:
SELECT DATEDIFF(SECOND,'1970-01-01', GETUTCDATE()) AS unix_timestamp
You can either create a user defined function to do this and use the query as-is or you can just modify the query like so:
n.created>(DATEDIFF(SECOND,'1970-01-01', '2019-02-28')) and n.created<(DATEDIFF(SECOND,'1970-01-01','2019-09-01'))
Unix timestamps are not particularly useful in SQL Server. You can add a computed column to convert this to a datetime data type:
alter table t add created_dt as (dateadd(second, created, '1970-01-01')) persisted;
create index t_created_dt on t(created_dt);
This then allows you to write:
n.created_dt > '2019-02-28' and
n.created_dt < '2019-09-01';
Otherwise, the solution by motobatsu is a good solution.

Validate dates before conversion, aka. ISDATE() equivalent

DB2 version is 9.7.0.7
I have a flat file, and need to validate fully prior to insert into a production table. For analysis, I've parsed it into a table where all columns are VARCHAR.
One of the tasks is to validate dates. I need to be able to locate the specific invalid dates, to report on the scope (frequency) and solution (reason).
I use ISDATE() in Sybase and SQL Server, which returns a 1 for a valid date, and a 0 for an invalid date. In Teradata, I left join to the SYS_CALENDAR table in the system catalog. It's been about 15 years since I've last been in a DB2 environment, but I believe analogs to either do not exist.
In this DB2 environment my role is limited to QA, meaning I cannot create T-SQL procedures or UDFs.
This thread is clever and makes me think there may be some Common Table Expression logic that could be employed in a query:
ISDATE equivalent of DB2
That one falls short as a solution, however, because it only considers format - the presence of an invalid (but properly formatted) date like '2016-04-31' or '2016-02-30' will raise an error and the query will return no rows.
I need to return all rows, identifying if each is valid or invalid (or just return the invalid rows for investigation, even) - so doing a CAST or CONVERT, or inserting into a formatted table in a test environment won't work.
Is there an analog to ISDATE(), SYS_CALENDAR, or another solution that gets to the same end product of a row-wise presentation of dates that can't be cast to DATE, prior to performing that conversion/insert?
You can do it with the PureXML extension as follows:
SELECT
XMLCAST(XMLQUERY('string($D) castable as xs:date' PASSING mycolumn as D ) AS INT)
FROM
mytable
which will return 1 or 0.

concatenate string in sql

I have a database table "create table t (s varchar, i int)" with 100 records.
When I want to sum all 'i' fields, I invoke something like "select sum(i) from t". Is there a way to concatenate the 's' fields? (select concatenate(s) from t)
In any sql dialect?
In any sql dialect?
There isn't an ANSI SQL specified way to do this across all SQL dialects. If you want specific solutions for a particular DBMS, then sure, some have a ready made solution, and others have generalized solutions that are more complicated.
e.g.
Oracle = WM_CONCAT
MySQL = GROUP_CONCAT
SQL Server = UDF / FOR XML PATH('') / recursive CTE
You need a question for each RDBMS you need the solution for, but you will find duplicate questions for each case already on StackOverflow.