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リモートクエリを強制的にローカルではなくリモートでフィルタリングする
私は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
@ 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年より前になるとは思わない場合でも、それは良い習慣です。クエリで参照するカレンダーテーブルの設定を調べているときに、これに遭遇しました。
クエリがOracleデータベースで実行されている場合は、固定フォーマットを使用する[〜#〜] ansi [〜#〜]日付リテラルを使用することをお勧めしますYYYY-MM-DD =。
例えば、
DATE '2015-10-20'
Oracleでは、'20140701'
はstringであり、[〜#〜] date [〜#〜]ではありません。 暗黙的なデータ型変換を見て、クライアントのロケール固有のNLS設定に基づいて結果を取得できるのは幸運かもしれません。あなたは常にそれを避けるべきです、そしてexplicitlyは日付比較のために文字列を日付に変換します。