从链接到Oracle的SQL Server编写SQL查询时,如何指定日期文字?

Ric*_*d A 8 sql sql-server oracle date-formatting

我有一个链接到Oracle 12.1数据库的SQL Server 12.0数据库.

我想在SQL Server数据库中创建一个视图,该视图从按日期过滤的Oracle表中返回数据.Oracle表在日期列上有一个索引.

成功运行的查询是:

select * from ORADB..SCHEMA.MYTABLE where MYDATE >= '20140701';
Run Code Online (Sandbox Code Playgroud)

然而,这运行得非常缓慢.我假设这是因为比较发生在SQL Server中,所以每行都被返回.

如果我走:

DECLARE @earliest date = '20140701';
select * from ORADB..SCHEMA.MYTABLE where MYDATE >= @earliest;
Run Code Online (Sandbox Code Playgroud)

然后它运行得很快,大概是因为条件被传递给Oracle所以正在使用表上的Oracle索引.

我的问题是我想创建一个视图.我找不到使用第二版代码创建视图的方法.如果我只是这样做:

create myview as select * from ORADB..SCHEMA.MYTABLE where MYDATE >= '20140701';
Run Code Online (Sandbox Code Playgroud)

然后它运行缓慢.

是否有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
Run Code Online (Sandbox Code Playgroud)

编辑:我刚刚发现了一个非常类似的问题:强制SQL远程查询过滤而不是本地过滤

Shn*_*ugo 19

我更喜欢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
Run Code Online (Sandbox Code Playgroud)

简单的日期文字不是文化独立的......

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
Run Code Online (Sandbox Code Playgroud)

但它的作用 - 然而 - 与目标类型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
Run Code Online (Sandbox Code Playgroud)

Thx to lad2025我想为completness添加"完整"的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
Run Code Online (Sandbox Code Playgroud)

  • @Shungo也许我对ISO格式不够具体[ISO 8601格式](https://technet.microsoft.com/en-us/library/ms190977%28v=sql.90%29.aspx)`的优势在于使用ISO 8601格式是它是一个国际标准.使用此格式指定的日期时间值是明确的`和**`此外,此格式不受SET DATEFORMAT或SET LANGUAGE设置的影响.**但是您必须使用带有时间部分的完整规范. (2认同)

Ric*_*bit 6

我建议使用@ lad2025建议的完整ISO 8601格式:

'2017-10-06T14:57:23'
Run Code Online (Sandbox Code Playgroud)

这优于@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;
Run Code Online (Sandbox Code Playgroud)

即使您不认为要使用的日期都在1753年之前,这也是一个很好的习惯。我在设置日历表以查询查询时遇到了这种情况。


Lal*_*r B 3

如果查询在 Oracle 数据库上运行,那么我建议使用ANSI日期文字,它使用固定格式YYYY-MM-DD

例如,

DATE '2015-10-20'
Run Code Online (Sandbox Code Playgroud)

在 Oracle 中,'20140701'字符串而不是DATE。您可能很幸运地看到隐式数据类型转换并根据客户端的特定于区域设置的 NLS 设置获得结果。您应该始终避免它,并显式地将字符串转换为日期以进行日期比较。

  • 谢谢拉利特,我知道'20140701'是Oracle中的一个字符串。我无法使用语法 DATE '2015-10-20' 因为 SQL Server 不理解它。如果我直接在 Oracle 中编写查询,我就会使用它。我尝试过多种日期格式。我在网上找到的有关 SQL Server 中日期文字的所有建议都建议使用 20140701 而不是 2014-07-01。 (2认同)