Sql-Server

導致隱式轉換的使用者定義數據類型

  • February 14, 2019

使用者定義的數據類型,我正在查看一些執行計劃,並看到當聲明 var 的類型為使用者定義的數據類型並從使用該使用者定義的數據類型的列中將值拉入該 var 時,在後台發生的隱式轉換,它是將其顯示為隱式轉換。這是它正常執行的方式嗎?

添加

好的,所以在 Programmability -> Types -> User-Defined Data Types 下:有

dbo.BOOL(char(1), not null)

ImageAccessibleFLAG TYPE_NAME is BOOL

新測試

我可以通過在數據庫中執行以下 reasonforcreatetype is char(1) 來進行隱式轉換

declare @test char(1)
set @test = (select top 1 reasonforcreatetype from result)
select @test

<ScalarOperator ScalarString="CONVERT_IMPLICIT(char(1),[Result].[ReasonForCreateType],0)">

現在我創建一個帶有 char(1) 和 bool 的新表。執行相同的查詢,我沒有得到隱式轉換。

更新 2

好的,當在同一張表下添加新列時出現問題,我得到以下資訊

Warning: Columns have different ANSI_PADDING settings.
New columns will be created with ANSI_PADDING 'on'.

我現在假設這與它有關,但我不確定修復或糾正這些問題的正確方法。

好的,這是一個再現:

USE tempdb;
GO
-- create one table with padding off:
SET ANSI_PADDING OFF;
GO
CREATE TABLE dbo.ap_off(a CHAR(1),
CONSTRAINT ck_apOff CHECK (a IN ('N','Y')));
GO
-- and other with padding on:
SET ANSI_PADDING ON;
GO
CREATE TABLE dbo.ap_on(a CHAR(1),
CONSTRAINT ck_apOn CHECK (a IN ('N','Y')));
GO

-- now, let's test queries 
-- with padding on or off
SET ANSI_PADDING OFF;
GO
-- implicit conversion:
DECLARE @off CHAR(1) = (SELECT a FROM dbo.ap_off);
-- implicit conversion:
DECLARE @on  CHAR(1) = (SELECT a FROM dbo.ap_on);

SET ANSI_PADDING ON;
GO
-- implicit conversion:
DECLARE @off CHAR(1) = (SELECT a FROM dbo.ap_off);
-- NO implicit conversion:
DECLARE @on  CHAR(1) = (SELECT a FROM dbo.ap_on);
GO

DROP TABLE dbo.ap_off, dbo.ap_on;

這是前三個查詢的相同版本的計劃:

在此處輸入圖像描述

第四,缺少計算標量和任何隱式轉換:

在此處輸入圖像描述

所以,正如我上面所建議的,這與別名類型沒有任何關係,而是在ANSI_PADDING很多方面都有問題的事實(這裡有一篇及時的文章一個 Stack Overflow 問題,以及來自 SQL Server 的 Microsoft 自己的文件2005 告訴你停止使用它)。

我建議的方法是使用這些非列建構任何表的新版本ANSI_PADDING(當然這次ANSI_PADDING ON是),遷移數據,刪除舊表,然後重命名新表。或者僅對單個列執行相同類型的操作(在任何一種情況下,這都是您可能希望在維護視窗期間執行的複雜且具有破壞性的操作)。

您可以通過以下方式辨識受影響的表:

SELECT s.name, t.name
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
ON s.[schema_id] = t.[schema_id]
WHERE t.is_ms_shipped = 0
AND EXISTS (SELECT 1 FROM sys.columns
WHERE [object_id] = t.[object_id]
AND is_ansi_padded = 0);

我會先用一個表或列來做這件事,看看是否值得。請注意,除了消除隱式轉換(您認為這可能會導致性能問題)之外,您還應該證明沒有它們,性能實際上會有所不同 - 並且差異足以證明努力、風險和潛在的停機時間是合理的。否則,值得去做嗎?我們無法回答這個問題,只有您和您的利益相關者可以回答。

引用自:https://dba.stackexchange.com/questions/73518