首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这种显式强制转换只会导致链接服务器出现问题?

为什么这种显式强制转换只会导致链接服务器出现问题?
EN

Database Administration用户
提问于 2016-08-17 07:42:58
回答 4查看 7.5K关注 0票数 21

我正在通过原始服务器上的视图从链接服务器查询数据。视图必须包括几个标准化列,如CreatedModifiedDeleted,但在本例中,源服务器上的表没有任何合适的信息。因此,列显式地转换为各自的类型。更新视图,将列更改为

代码语言:javascript
复制
NULL AS Modified

代码语言:javascript
复制
CAST(NULL as DateTime) as Modified

但是,执行此更新后,视图将触发以下错误消息:

MSG7341、级别16、状态2、第3行无法从OLE DB提供程序"SQLNCLI11“获得列”(用户生成的表达式)“的当前行值。

我们已经在源服务器上进行了“显式强制转换”(-change),而且我怀疑这个问题可能与所涉及的服务器版本有关。我们真的不需要使用这个石膏,但它感觉更干净。现在我只是好奇为什么会发生这种事。

服务器版本(原版):

Microsoft 2012-11.0.5058.0 (X64) 2014年5月14日18:34:29版权(c)微软公司企业版(64位) Windows 6.1 (Build 7601: Service Pack 1) (Hypervisor)

服务器版本(链接):

微软Server 2008 R2 (SP1) - 10.50.2500.0 (X64) 2011年6月17日00:54:03版权(c)微软公司企业版(64位)在WindowsNT6.1 (Build 7601: Service Pack 1) (Hypervisor)

编辑

我刚刚意识到我犯了一个错误,我没有发布所有相关的专栏,我必须为遗漏一个重要的细节而道歉。我不知道我怎么没注意到。不过,问题仍然存在。

错误的转换不是发生在对DateTime的强制转换中,而是发生在将一列强制转换为UniqueIdentifier时。

这就是罪魁祸首:

代码语言:javascript
复制
CAST(NULL AS UniqueIdentifier) AS [GUID]

server 2008 UniqueIdentifiers支持R2,正如注释中提到的,视图执行的查询在链接服务器上运行良好。

EN

回答 4

Database Administration用户

发布于 2016-08-22 14:05:14

只有一个糟糕的解决办法--使用一些日期常量,比如'1900-01-01',而不是null

代码语言:javascript
复制
CAST('1900-01-01' as DateTime) as Modified

导入之后,您可以用1900-01-01更新列到Null。

按照这里的说法,这是一种SQL 2012特性/bug。

编辑:将1900-00-00替换为有效日期1900-01-01,如下面的@a_horse_with_no_name注释所示。

票数 4
EN

Database Administration用户

发布于 2016-08-25 12:54:39

该问题与数据类型转换有关(如注释中所述)。

请考虑以下几点:

代码语言:javascript
复制
SELECT NULL as NullColumn INTO SomeTable;
EXEC sp_help SomeTable;
DROP TABLE SomeTable;

注意,NullColumnint类型的。Server不喜欢将int值转换为uniqueidentifier。此SELECT语句在数据类型转换时将失败:

代码语言:javascript
复制
--Just a SELECT from nothing
SELECT CAST(CAST(NULL as int) as uniqueidentifier);
--
--or to see it from a physical table:
SELECT NULL as NullColumn INTO SomeTable;
SELECT CAST(NullColumn as uniqueidentifier) FROM SomeTable;
DROP TABLE SomeTable;

不允许将Msg 529、级别16、状态2、第3行从数据类型int显式转换为unique标识符。

虽然可以将此特定值(NULL)转换为GUID,但Server将根据数据类型转换抛出错误,甚至在查看特定值之前。相反,您需要执行多步CAST操作才能将隐式int更改为可以清晰地转换为uniqueidentifer的数据类型--这意味着先转换为varchar,然后转换为uniqueidentifier

代码语言:javascript
复制
--Just a SELECT from nothing
SELECT CAST(CAST(CAST(NULL as int) as varchar) as uniqueidentifier);
--
--or to see it from a physical table:
SELECT NULL as NullColumn INTO SomeTable;
SELECT CAST(CAST(NullColumn as varchar(32)) as uniqueidentifier) FROM SomeTable;
DROP TABLE SomeTable;
票数 2
EN

Database Administration用户

发布于 2016-08-24 14:50:19

“任择议定书”最终可以决定这是否是一个适当的答案。

我没有“绝对”的证据,但我“怀疑”这个问题源于这样一个事实,即UniqueIdentifer依赖于服务器,而且提供者可能很难找到从哪个服务器(本地或远程)获取这个unique标识符,尽管它是空的。这就是为什么您可能可以成功地在此场景中转换任何其他数据类型,但不能转换uniqueidentifier。“服务器”依赖的数据类型(如UNIQUEIDENTIFIERS和DATETIMEOFFSET )将提供您遇到的错误。

使用OPENQUERY代替4部分的名称有效。

代码语言:javascript
复制
set nocount on  
DECLARE @cmd nVARCHAR(max)
DECLARE @datatype SYSNAME

DECLARE _CURSOR CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY
FOR
SELECT NAME
FROM sys.types 

OPEN _CURSOR

FETCH NEXT
FROM _CURSOR
INTO @datatype

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        SET @cmd = 'select top 1 cast(null as ' + @Datatype + ') as CastedData from remoteserver.remotedatabase.remoteschema.remotetable'
        PRINT @cmd
        EXECUTE sp_executesql @cmd
    END TRY

    BEGIN CATCH
        PRINT Error_message()
    END CATCH

FETCH NEXT
FROM _CURSOR
INTO @datatype
END --End While

CLOSE _CURSOR

DEALLOCATE _CURSOR
票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/147039

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档