Using OPENQUERY with an Oracle database to query a date range - sql-server

We have an Oracle database that we access through OpenQuery for some stuff. You apparently can't do date comparisons directly in OpenQuery using the OleDB driver, so to get around this you have to convert the dates to Julien dates and compare those numbers. I have the following query that we're trying to execute this in MS SQL Server (GPROD is a Linked Server via the OleDb driver):
SELECT *
FROM OPENQUERY(GPROD, '
SELECT *
FROM ORD_HDR_HST
WHERE (cast(to_number(to_char(SHIP_DATE ,''J'')) as numeric(10,0)) >= cast(to_number(to_char(to_date(''01-JAN-2015'') ,''J'')) as numeric(10,0)) AND
cast(to_number(to_char(SHIP_DATE ,''J'')) as numeric(10,0)) <= cast(to_number(to_char(to_date(''21-SEP-2015'') ,''J'')) as numeric(10,0)) )')
This query returns no results but also produces no error.
If I execute this query in Oracle SQL Developer, it works just fine and returns thousands of rows:
SELECT *
FROM ORD_HDR_HST
WHERE (cast(to_number(to_char(SHIP_DATE ,'J')) as numeric(10,0)) >= cast(to_number(to_char(to_date('01-JAN-2015') ,'J')) as numeric(10,0)) AND
cast(to_number(to_char(SHIP_DATE ,'J')) as numeric(10,0)) <= cast(to_number(to_char(to_date('21-SEP-2015') ,'J')) as numeric(10,0)) )
The SHIP_DATE field is of type DATE and is nullable, if that matters.
Does anyone know what I can do to get this working through OpenQuery?
Edit:
I did a test of the Julien Date conversion and there's definitely something fishy going on, but I don't know what's causing it. If I execute this in Oracle:
select cast(to_number(to_char(to_date('01-JAN-2015') ,'J')) as numeric(10,0)) from dual
I get 2457024
If I execute this on SQL Server:
select * from OPENQUERY(GPROD, 'select cast(to_number(to_char(to_date(''01-JAN-2015'') ,''J'')) as numeric(10,0)) from dual')
I get 1721443

I found a solution to the problem. By specifying a mask for the date, it will provide the proper results. Using:
to_char(to_date('01-JAN-2015','DD-MON-YYYY') ,'J')
instead of
to_char(to_date('01-JAN-2015') ,'J')
Gives the same result through OpenQuery and directly from Oracle.

Related

REGEXP_SUBSTR equivalent in SQL Server

I have an Oracle query using
SELECT REGEXP_SUBSTR('500 Oracle Parkway, Redwood Shores, CA',',[^,]+,')
FROM DUAL;
It returns the output as below:
, Redwood Shores,
I am trying to get the exact same result in SQL Server. I tried to do it as below
substring(text, patindex, length)
But I struggled with length specification.
Can you please let me know how I can achieve this is in SQL Server?
You can try below query
WITH dual AS
(
SELECT '500 Oracle Parkway, Redwood Shores, CA' AS st
)
SELECT SUBSTRING(REVERSE(SUBSTRING(REVERSE(st),
CHARINDEX(',', REVERSE(st)),
LEN(st))),
CHARINDEX(',', st),
LEN(st)) str_value
FROM dual
Below is the result which I have got
Note: with clause is just for data preparation. Just make use of the substring part in select statement
Try this:
Declare #test varchar(max)='500 Oracle Parkway, Redwood Shores, CA'
select reverse(substring(reverse(substring(#test,charindex(',',#test),len(#test))),
charindex(',',reverse(substring(#test,charindex(',',#test),len(#test)))),
len(substring(#test,charindex(',',#test),len(#test)))))

How to pass SSIS variables in ODBC SQLCommand expression?

I'm trying to load incremental data from ODBC server to SQL server using common table expression.
When running the query in the Dbeabver application, is executed correctly:
with test as
(
SELECT userid,sum(goldbalance)
FROM Server.events_live
where eventTimestamp>=DATE '2016-01-01' + INTERVAL '-100 day'
group by userid
order by sum(goldbalance) desc)
)
select * from test
when running it from an sql command expression of the ODBC source, it fails due to wrong syntax. It looks as follow:
with test as
(
SELECT userid,sum(goldbalance)
FROM deltadna.events_live
where eventTimestamp>=DATE '"+#[User::datestring]+"' + INTERVAL '-100 day'
group by userid
order by sum(goldbalance) desc)
)
select * from test"
the datestring variable is getting the server date and convert it to string in the format yyyy-mm-dd. I'm usually use this method to pull data from ADO.NET and it works properly.
Is there any other way to pull incremental data from ODBC server using ssis variables?
With OLE DB
Try this code, it works for me with my own tables with SQL Server :
SELECT userid,sum(goldbalance) AS SUMGOLD
FROM deltadna.events_live
WHERE eventTimestamp >= DATEADD(DAY, -100,CONVERT(DATE,?))
GROUP BY userid
ORDER BY SUMGOLD desc
You have to click on Parameters in the OLEDB Source Editor to configure what you need. Use the '?' to represent a variable in your query.
If you query if too complicated, stored it in a stored procedure and call it like this:
EXEC shema.storedProcedureName ?
And map the '?' to your variable #user::DateString
With ODBC
The expressions are outside the data flow in Data Flow Properties.
Select the expression property and add your dynamic query.
And your expression will be
"SELECT userid,sum(goldbalance) AS SumGold
FROM deltadna.events_live
where eventTimestamp>=DATE "+#[User::datestring]+" +INTERVAL '-100 day'
group by userid
order by SumGold desc"

Convert Access query to SQL

I am converting Access query to SQL Server.
I want to convert below lines to SQL
1. Format (210.6, "Standard")
2. Format (210.6, "#,##0.00")
How do i convert it to SQL query.
I have tried with below, but still not able to find the solution.
For the first query, i found below solution, which is correct
1. CONVERT(varchar, CAST(tSRO.OutputF11 AS money), 1)
Now, for second query, i do not know what i have to do.
From SQL Server 2012+ you can use FORMAT:
SELECT FORMAT(210.6, '#,##0.00') -- 210.60
SELECT FORMAT(1210.6, '#,##0.00') -- 1,210.60
LiveDemo
SQL Server before 2012:
SELECT REPLACE(CONVERT(VARCHAR,CONVERT(MONEY, 1210.6),1),'.00','') -- 1,210.60
LiveDemo2
Warning:
This operation is pure for presentation layer and should be done in application.

Datetime BETWEEN statement not working in SQL Server

I have the following query,
SELECT * FROM LOGS
WHERE CHECK_IN BETWEEN CONVERT(datetime,'2013-10-17') AND CONVERT(datetime,'2013-10-18')
this query not returning any result, but the following query return the result,
SELECT * FROM LOGS WHERE CHECK_IN >= CONVERT(datetime,'2013-10-17')
why the first query not returning any result? If I did any mistake pls correct me.
Do you have times associated with your dates? BETWEEN is inclusive, but when you convert 2013-10-18 to a date it becomes 2013-10-18 00:00:000.00. Anything that is logged after the first second of the 18th will not shown using BETWEEN, unless you include a time value.
Try:
SELECT
*
FROM LOGS
WHERE CHECK_IN BETWEEN
CONVERT(datetime,'2013-10-17')
AND CONVERT(datetime,'2013-10-18 23:59:59:998')
if you want to search the entire day of the 18th. I set miliseconds to 998 because SQL Server was pulling in 2013-10-19 00:00:00:0000 in the query.
SQL DATETIME fields have milliseconds. So I added 999 to the field.
Does the second query return any results from the 17th, or just from the 18th?
The first query will only return results from the 17th, or midnight on the 18th.
Try this instead
select *
from LOGS
where check_in >= CONVERT(datetime,'2013-10-17')
and check_in< CONVERT(datetime,'2013-10-19')
From Sql Server 2008 you have "date" format.
So you can use
SELECT * FROM LOGS WHERE CONVERT(date,[CHECK_IN]) BETWEEN '2013-10-18' AND '2013-10-18'
https://learn.microsoft.com/en-us/sql/t-sql/data-types/date-transact-sql
You don't have any error in either of your queries.
My guess is the following:
No records exists between 2013-10-17' and '2013-10-18'
the records the second query returns you exist after '2013-10-18'
You need to convert the date field to varchar to strip out the time, then convert it back to datetime, this will reset the time to '00:00:00.000'.
SELECT *
FROM [TableName]
WHERE
(
convert(datetime,convert(varchar,GETDATE(),1))
between
convert(datetime,convert(varchar,[StartDate],1))
and
convert(datetime,convert(varchar,[EndDate],1))
)
DROP TABLE IF EXISTS #TB_PERIODO_TEMP CREATE TABLE #TB_PERIODO_TEMP (DATA DATETIME)
INSERT INTO #TB_PERIODO_TEMP VALUES
('22-12-2022 00:00:00'),
('22-12-2022 23:59:59'),
('23-12-2022 00:00:00'),
('23-12-2022 23:59:59')
SELECT * FROM #TB_PERIODO_TEMP -- ALL
SELECT * FROM #TB_PERIODO_TEMP WHERE DATA
BETWEEN '22-12-2022' AND '23-12-2022' --OLÉ!!!
--BETWEEN CONSIDERING PERIODS WITH HOURS O/
SELECT * FROM #TB_PERIODO_TEMP WHERE DATA
BETWEEN '22-12-2022' AND '23-12-2022 23:59:59:999'

Convert oracle date string to SQL Server datetime

In a SQL Server 2000 DB, I have a table which holds string representations of Oracle DB dates. They are formatted like "16-MAY-12". I need to convert these to datetime. I can not seem to find a conversion style number that matches, nor can I find a function that will allow me to specify the input format. Any ideas?
This seems to work for me:
SELECT CONVERT(DATETIME, '16-MAY-12');
You can also try using TO_CHAR() to convert the Oracle values to a more SQL Server-friendly format (best is YYYYMMDD) before pulling them out of the darker side.
Follow Aaron's advice and cast to string on the Oracle side and then did a check/recast on the MS SQL side. See example below:
;WITH SOURCE AS (
SELECT * FROM openquery(lnk,
'SELECT
TO_CHAR(OFFDATE , ''YYYY-MM-DD HH24:MI:SS'') AS OFFDATE,
FROM
ORACLE_SOURCE')),
SOURCE_TRANSFORM AS
(
SELECT
CASE
WHEN ISDATE(OFFDATE) = 1 THEN CAST(OFFDATE AS DATETIME)
ELSE NULL END AS OFFDATE
FROM
SOURCE
)
SELECT * FROM SOURCE_TRANSFORM

Resources