web-dev-qa-db-ja.com

OracleにリンクされているSQL ServerからSQLクエリを書き込むときに日付リテラルを指定するにはどうすればよいですか?

Oracle 12.1データベースにリンクされているSQL Server 12.0データベースがあります。

SQL Serverデータベースに、日付でフィルターされたOracleテーブルからデータを返すビューを作成します。 Oracleテーブルの日付列にインデックスがあります。

正常に機能するクエリは次のとおりです。

select * from ORADB..SCHEMA.MYTABLE where MYDATE >= '20140701';

ただし、これは非常にゆっくり実行されます。 SQL Serverで比較が行われるため、すべての行が返されるためだと思います。

もし私が行くならば:

DECLARE @earliest date = '20140701';
select * from ORADB..SCHEMA.MYTABLE where MYDATE >= @earliest;

次に、おそらく条件がOracleに渡されてテーブルのOracleインデックスが使用されているため、高速で実行されます。

私の問題は、ビューを作成することです。コードの2番目のバージョンを使用してビューを作成する方法が見つかりません。私が単に行う場合:

create myview as select * from ORADB..SCHEMA.MYTABLE where MYDATE >= '20140701';

その後、ゆっくりと実行されます。

SQL ServerがOracleに渡す日付リテラルの別の形式はありますか、それとも別の解決策がありますか?また、それがOracleへのリンクの作成に使用されたパラメーターと関係があるのか​​どうかも疑問に思いました。参考までに、次のとおりです。

USE [master]
GO
EXEC master.dbo.sp_addlinkedserver @server = N'ORADB', @srvproduct=N'Oracle', @provider=N'OraOLEDB.Oracle', @datasrc=N'DPDB'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ORADB',@useself=N'False',@locallogin=NULL,@rmtuser=N'MYUSER',@rmtpassword='#######'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'collation compatible', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'data access', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'dist', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'pub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'rpc', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'rpc out', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'sub', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'connect timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'collation name', @optvalue=null
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'lazy schema validation', @optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'query timeout', @optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'use remote collation', @optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'ORADB', @optname=N'remote proc transaction promotion', @optvalue=N'true'
GO

編集:私は非常によく似た質問を見つけました: SQLリモートクエリを強制的にローカルではなくリモートでフィルタリングする

10
Richard A

私はODBC形式を好みます:

--DateTime
SELECT {ts'2015-09-20 12:30:00'}
--Time (however this comes with "today"-time)
SELECT {t'12:30:00'}
--Date
SELECT {d'2015-09-20'}
GO

単純な日付リテラルは文化に依存しません...

SET LANGUAGE ENGLISH;
SELECT CAST('2014-09-13' AS DATETIME);
GO
SET LANGUAGE GERMAN;
SELECT CAST('2014-09-13' AS DATETIME);--ERROR: there's no month "13"
GO

しかし、それは機能しますが、ターゲットタイプDATEを使用します(この違いはかなり奇妙です...):

SET LANGUAGE ENGLISH;
SELECT CAST('2014-09-13' AS DATE);
GO
SET LANGUAGE GERMAN;
SELECT CAST('2014-09-13' AS DATE);--ERROR: there's no month "13"
GO

Thx to lad2025完全に機能する「完全な」ISO 8601を追加します。

SET LANGUAGE ENGLISH;
SELECT CAST('2014-09-13T12:30:00' AS DATETIME);
GO
SET LANGUAGE GERMAN;
SELECT CAST('2014-09-13T12:30:00' AS DATETIME);
GO
19
Shnugo

@ lad2025で提案されているように、完全なISO 8601形式を使用することをお勧めします。

'2017-10-06T14:57:23'

これは、@ Shnugoが提案するODBCフォーマットより優れています。

SQL Server 2014では、ODBC形式は1753-01-01より前の日付(たとえば、古いDATETIMEデータ型の範囲外の日付)では機能しませんが、ISO 8601形式はそうです。

これを自分でテストするには、次のクエリを試してください。

--This will work
DECLARE @DateISO DATE = '0001-01-01T00:00:00';
SELECT @DateISO;

--This will also work
DECLARE @DatetimeISO DATETIME2 = '0001-01-01T00:00:00';
SELECT @DatetimeISO;

--This will not work
DECLARE @DateODBC DATE = {D '0001-01-01'};
SELECT @DateODBC;

--This will also not work
DECLARE @DatetimeODBC DATETIME2 = {ts '0001-01-01 00:00:00'};
SELECT @DatetimeODBC;

作業している日付が1753年より前になるとは思わない場合でも、それは良い習慣です。クエリで参照するカレンダーテーブルの設定を調べているときに、これに遭遇しました。

5
Tidorith

クエリがOracleデータベースで実行されている場合は、固定フォーマットを使用する[〜#〜] ansi [〜#〜]日付リテラルを使用することをお勧めしますYYYY-MM-DD =。

例えば、

DATE '2015-10-20'

Oracleでは、'20140701'stringであり、[〜#〜] date [〜#〜]ではありません。 暗黙的なデータ型変換を見て、クライアントのロケール固有のNLS設定に基づいて結果を取得できるのは幸運かもしれません。あなたは常にそれを避けるべきです、そしてexplicitlyは日付比較のために文字列を日付に変換します。

2
Lalit Kumar B