我正在通过原始服务器上的视图从链接服务器查询数据。视图必须包括几个标准化列,如Created、Modified和Deleted,但在本例中,源服务器上的表没有任何合适的信息。因此,列显式地转换为各自的类型。更新视图,将列更改为
NULL AS Modified至
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时。
这就是罪魁祸首:
CAST(NULL AS UniqueIdentifier) AS [GUID]server 2008 UniqueIdentifiers支持R2,正如注释中提到的,视图执行的查询在链接服务器上运行良好。
发布于 2016-08-22 14:05:14
只有一个糟糕的解决办法--使用一些日期常量,比如'1900-01-01',而不是null。
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注释所示。
发布于 2016-08-25 12:54:39
该问题与数据类型转换有关(如注释中所述)。
请考虑以下几点:
SELECT NULL as NullColumn INTO SomeTable;
EXEC sp_help SomeTable;
DROP TABLE SomeTable;注意,NullColumn是int类型的。Server不喜欢将int值转换为uniqueidentifier。此SELECT语句在数据类型转换时将失败:
--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:
--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;发布于 2016-08-24 14:50:19
“任择议定书”最终可以决定这是否是一个适当的答案。
我没有“绝对”的证据,但我“怀疑”这个问题源于这样一个事实,即UniqueIdentifer依赖于服务器,而且提供者可能很难找到从哪个服务器(本地或远程)获取这个unique标识符,尽管它是空的。这就是为什么您可能可以成功地在此场景中转换任何其他数据类型,但不能转换uniqueidentifier。“服务器”依赖的数据类型(如UNIQUEIDENTIFIERS和DATETIMEOFFSET )将提供您遇到的错误。
使用OPENQUERY代替4部分的名称有效。
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 _CURSORhttps://dba.stackexchange.com/questions/147039
复制相似问题