我正在升級幾個相同的資料庫副本,這些副本可能已經部分升級,出于某種原因,布林值存盤在nvarchar(5).
因此,在下面(存在于INSERT>SELECT塊內)中,我需要檢查該列是否ShowCol存在,如果不存在則用 0 填充,或者如果存在則用評估字串 bool 的結果填充它:
CASE
WHEN COL_LENGTH('dbo.TableName', 'ShowCol') IS NULL THEN 0
ELSE IIF(LOWER(ShowCol) = 'false', 0, 1)
END
...但我收到錯誤“無效的列名'ShowCol'”。我似乎無法短路這個,你能幫忙嗎?
值得注意的是,如果該列確實存在,則包含“false”、“False”和“FALSE”的混合,所以這就是LOWER(). (True 列也偶爾需要處理尾隨空格,這就是為什么我只處理 False 而其他一切都是真實的。)
我懷疑這是因為這種包裝LOWER()導致服務器始終評估運算式。
uj5u.com熱心網友回復:
您不能使列的存在短路(它與 無關LOWER();如果您將其洗掉,則什么都不會改變)。
您將需要動態 SQL,例如:
DECLARE @sql nvarchar(max) = N'UPDATE trg SET
trg.col1 = src.col1,
trg.col2 = src.col2';
IF COL_LENGTH('dbo.TableName', 'ShowCol') > 0
BEGIN
SET @sql = N', trg.ShowCol = IIF(LOWER(src.ShowCol) = ''false'', 0, 1)';
END
SET @sql = N' ...
FROM dbo.TableName AS trg
INNER JOIN dbo.Origin AS src
ON ...';
EXEC sys.sp_executesql @sql; -- ,N'params', @params;
當您選擇資料時,您可以通過引入常量來代替列來欺騙決議器,利用 SQL Server 的愿望,即使在與語法建議不同的范圍內也能找到列參考。我在Make SQL Server DMV Queries Backward Compatible中談到了這一點。我不知道有任何直接的方法可以在沒有動態 SQL 的情況下使用寫入,因為決議器在那里進行更嚴格的檢查,因此更難被愚弄。
想象一下你有這些表:
CREATE TABLE dbo.SourceTable(a int, b int, c int);
INSERT dbo.SourceTable(a,b,c) VALUES(1,2,3);
CREATE TABLE dbo.DestinationWithAllColumns(a int, b int, c int);
INSERT dbo.DestinationWithAllColumns(a,b,c) VALUES(1,2,3);
CREATE TABLE dbo.DestinationWithoutAllColumns(a int, b int);
INSERT dbo.DestinationWithoutAllColumns(a,b) VALUES(1,2);
您可以針對它們中的任何一個撰寫一個SELECT生成名為 int 的輸出列c:
;WITH optional_columns AS
(
SELECT c = CONVERT(int, NULL)
)
SELECT trg.a, trg.b, trg.c
FROM optional_columns
CROSS APPLY
(SELECT a,b,c FROM dbo.DestinationWithAllColumns) AS trg
INNER JOIN dbo.SourceTable AS src ON src.a = trg.a;
輸出:
| 一種 | b | C |
|---|---|---|
| 1 | 2 | 3 |
;WITH optional_columns AS
(
SELECT c = CONVERT(int, NULL)
)
SELECT trg.a, trg.b, trg.c
FROM optional_columns
CROSS APPLY
(SELECT a,b,c FROM dbo.DestinationWithoutAllColumns) AS trg
INNER JOIN dbo.SourceTable AS src ON src.a = trg.a;
輸出:
| 一種 | b | C |
|---|---|---|
| 1 | 2 | 空值 |
到現在為止還挺好。但是,一旦您嘗試更新:
;WITH optional_columns AS
(
SELECT c = CONVERT(int, NULL)
)
UPDATE trg SET trg.b = src.b, trg.c = src.c
FROM optional_columns
CROSS APPLY
(SELECT a,b,c FROM dbo.DestinationWithoutAllColumns) AS trg
INNER JOIN dbo.SourceTable AS src ON src.a = trg.a;
訊息 4421,級別 16,狀態 1
派生表“trg”不可更新,因為派生表的列是派生的或不變的。
- 示例db<>fiddle
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/460713.html
上一篇:查詢Json陣列列和其他當前表列
