中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SQL語法提示工具SQL Prompt,幫你認識SQL_VA

發布時間:2020-02-28 18:15:17 來源:網絡 閱讀:617 作者:wx5d39183e901c5 欄目:關系型數據庫

SQL Prompt根據數據庫的對象名稱、語法和代碼片段自動進行檢索,為用戶提供合適的代碼選擇。自動腳本設置使代碼簡單易讀--當開發者不大熟悉腳本時尤其有用。SQL Prompt安裝即可使用,能大幅提高編碼效率。此外,用戶還可根據需要進行自定義,使之以預想的方式工作。

本教程說明了SQL_VARIANT數據類型的“怪癖”,以及為什么最好調查SQL Prompt何時提醒您使用它。如果在使用之前將其顯式轉換為真實類型,那么將數據存儲為SQL_VARIANT才是唯一安全的。

sql_variant數據類型來自幾個不同數據類型的值,并由SQL Server在內部使用。它不是SQL標準的一部分,在關系數據庫中的用途有限。需要小心處理它,因為它的誤用會導致難以追蹤的性能問題和bug。sql_variant不能直接傳遞給某些SQL運算符和函數,例如LIKE、SUM()或者AVG(),并且在比較或表達式中使用時會產生誤導性結果。除二進制數據外,它不能通過ODBC返回到應用程序。

SQL Server是一種強類型語言,這樣做是為了確保數據完整性、高效存儲和有效檢索。由于這個原因,使用sql_variant有點奇怪,因此通過不明智地使用它會無意中造成問題也就不足為奇了。出于這些原因,SQL Prompt強制執行“最佳實踐”代碼分析規則(BP024),該規則將提醒您使用sql_variant數據類型。

SQL語法提示工具SQL Prompt,幫你認識SQL_VA

與許多“最佳實踐”規則一樣,這些建議有時聽起來像是告訴人們在拿著剪刀時不要跑。在這種情況下,只有在使用數據sql_variant之前將其顯式轉換為真實類型,才能將數據存儲為安全。

為什么有sql_variant?

sql_variant數據類型是在微軟從Sybase開發的SQL Server時首次引入的。他們需要能夠從微軟首次進入數據庫市場的Microsoft Access將數據庫導入SQL Server,該市場支持變體數據類型。它仍然在SQL Server內部用于系統存儲過程的參數以及擴展屬性等數據。

sql_variant傾向于作為用戶定義函數返回的列、變量、參數或值的catch-all數據類型。它最多可以容納8000個字節,并且可以存儲基本數據類型,如整數、小數、字符串和日期。它不能存儲其他一些數據類型,例如(MAX)數據類型、CLR數據類型或XML。

有時,sql_variant可能是一個有用的工具,例如在處理不一致或未指定的數據類型時,這通常是因為數據庫支持允許用戶定義數據的應用程序。

它存儲所包含的值的基本數據類型,因此當它用作中介時,強制執行數據類型之間的所有轉換規則。您可以使用數據類型函數檢索此基本數據類型sql_variant_property():

DECLARE?@MyVariant?SQL_VARIANT?=?'2.3657'
??SELECT?SQL_VARIANT_PROPERTY(@MyVariant,'BaseType')

在這種情況下返回varchar。這里還有一些其他有用的屬性:Precision、Scale、TotalBytes、Collation和MaxLength。如果要從sql_variant生成主鍵,則TotalBytes參數使該函數可用作初步檢查,因為主鍵(或索引)的總大小限制為900字節。

順便提一句,您可以在任何數據類型上使用此函數。例如:

SELECT?SQL_VARIANT_PROPERTY(N'Béoáed?mac?Ocláin','collation')

聚合

讓我們看看如果我們嘗試聚合sql_variant列會發生什么。為了簡單起見,我們將從派生表中執行此操作。

SELECT?Sum(ValueAsVariant)
????FROM
??????(
??????VALUES?(Convert(SQL_VARIANT,?'one'),?1,?Convert(SQL_VARIANT,?1)),
?????????????('two',?2,?2),
?????????????('three',?3,?3),
?????????????('four',?4,?4),?
?????????????('five',?5,?5)
??????)?AS?f?(ValueAsString,?ValueAsInt,?ValueAsVariant);

我們看到一個錯誤:

Msg 8117,Level 16,State 1,Line 3操作數數據類型sql_variant對sum運算符無效。

而如果我們先顯式地轉換為數字(int、numeric等等),它工作正常。

SELECT?Sum(Convert(NUMERIC(9,4),?ValueAsVariant))
??--?try?sum,?avg,?stdev,?stdevp,?var,?varp,?or?string_agg
????FROM
??????(
??????VALUES?(Convert(SQL_VARIANT,?'one'),?1,?Convert(SQL_VARIANT,?1)),
?????????????('two',?2,?2),
?????????????('three',?3,?3),
?????????????('four',?4,?4),?
?????????????('five',?5,?5)
??????)?AS?f?(ValueAsString,?ValueAsInt,?ValueAsVariant);

在max()和min()聚合函數似乎很好地工作的sql_variant數據類型,所以不可能有技術問題阻止其他函數工作。

比較

您不能用LIKE過濾sql_variant列,因為LIKE它不支持sql_variant參數。

SELECT????f.ValueAsVariant,?f.ValueAsInt,?f.ValueAsString
????FROM
??????(
??????VALUES?(Convert(SQL_VARIANT,'one'),?1,?Convert(VARCHAR(5),1)),
?????????????('two',?2,?2),
?????????????('three',?3,?3),
?????????????('four',?4,?4),?
?????????????('five',?5,?5)
??????)?AS?f(ValueAsVariant,?ValueAsInt,?ValueAsString)
??????WHERE?ValueAsVariant?like?'t%'

錯誤時候這樣的:

Msg 8116,Level 16,State 1,Line 4

參數數據類型sql_variant對于LIKE函數的參數1無效。

實際上,沒有任何字符串函數接受sql_variant,并且不會嘗試對字符串進行隱式轉換。相反,他們只是拒絕參數。相反,如果我們聲明它到底是什么類型的數據類型,它的工作原理如下:

SELECT????f.ValueAsVariant,?f.ValueAsInt,?f.ValueAsString
????FROM
??????(
??????VALUES?(Convert(SQL_VARIANT,'one'),?1,?Convert(NVARCHAR(5),1)),
?????????????('two',?2,?2),
?????????????('three',?3,?3),
?????????????('four',?4,?4),?
?????????????('five',?5,?5)
??????)?AS?f(ValueAsVariant,?ValueAsInt,?ValueAsString)
??????WHERE?Convert(VARCHAR(20),ValueAsVariant)?like?'t%'

除非您sql_variant在WHERE子句中顯式轉換數據類型,否則在隱藏在漫長且曲折的過程中時,可能會得到不正確的結果,其原因很難檢測到。例如,這只返回第4行和第5行,這是您所期望的:

DECLARE?@ParameterAsINT?INT
??SELECT?@ParameterAsINT?=?3
??SELECT????f.ValueAsString,?f.ValueAsInt,?f.ValueAsVariant
????FROM
??????(
??????VALUES?('one',?1,?Convert(SQL_VARIANT,?1)),
?????????????('two',?2,?2),
?????????????('three',?3,?3),
?????????????('four',?4,?4),?
?????????????('five',?5,?5)
??????)?AS?f?(ValueAsString,?ValueAsInt,?ValueAsVariant)
??????WHERE?ValueAsVariant?>?@ParameterAsInt

但是,如果我們將參數更改為a sql_variant并為其提供字符串值,會發生什么?

DECLARE?@ParameterAsVariant?sql_variant?
??SELECT?@ParameterAsVariant?='3'
??SELECT????f.ValueAsString,?f.ValueAsInt,?f.ValueAsVariant
????FROM
??????(
??????VALUES?('one',?1,?Convert(SQL_VARIANT,?1)),
?????????????('two',?2,?2),
?????????????('three',?3,?3),
?????????????('four',?4,?4),?
?????????????('five',?5,?5)
??????)?AS?f?(ValueAsString,?ValueAsInt,?ValueAsVariant)
??????WHERE?ValueAsVariant?>?@ParameterAsVariant

現在它返回所有你可能不會想到的行。這里的問題是,為了評估表達式,SQL Server檢查它的基類型或類型族,并將其與我們的變量類型進行比較。sql_variant的基類型系列可以是Unicode、精確數字、近似數字、日期和時間、二進制或唯一標識符,我們的ValueAsVariant列包含精確數字。

在第一個僅返回第4行和第5行的示例中,我們的參數類型與ValueAsVariant列的類型屬于同一族。SQL Server執行隱式轉換,代碼可以正常工作。但是,在第二個示例中,我們使用sql_variant帶有字符串值的參數,其中@ParameterAsVariant包含Unicode。而不是將Unicode類型隱式轉換為精確數字(即“高級”數據類型),SQL Server判斷高級數據類型為“更大”,因此我們的搜索條件對每一行的計算結果為true。

這顯然是sql_variant的一個怪癖。如果我們比較完全相同的基本數據類型的兩個sql_variant值,它將“工作”。如果我們將sql_variant與同一系列中的另一種數據類型進行比較,隱式轉換將允許它工作。除此之外,一切都不可能了。

ODBC支持

ODBC不完全支持sql_variant。當使用與包含sql_variant類型的表的連接時,您會注意到這一點,因為sql_variant當您使用Microsoft OLE DB Provider for ODBC(MSDASQL)時,列中的數據將作為二進制數據(例如0x32303931)返回。

限制在索引中使用sql_variant

sql_variant僅當索引的總長度小于900字節的最大值時,才可以在索引中包含列。這意味著如果值的長度超過900個字節,則索引sql_variant列上的插入操作將失敗。如果我們創建表或表變量:

DECLARE?@MyTableVariable?TABLE?(MyProperty?sql_Variant?PRIMARY?KEY)

我們得到一個警告:

警告!聚簇索引的最大密鑰長度為900字節。索引“PK __#B2961DC__8E45D1198BEEA325”的最大長度為8016字節。對于某些大值組合,插入或更新操作將失敗。

如果我們忽略警告......

DECLARE?@MyTableVariable?TABLE?(MyProperty?sql_Variant?PRIMARY?KEY)
??INSERT?INTO?@MyTableVariable?(MyProperty)?
???VALUES?(N'Abbán?moccu?Corbmaic'),
????(N'Abel?of?Reims'),
????(N'Buíte?[Boetius]?mac?Brónaig'),
????(N'Buriana'),
????(Replicate(N'Caillín?[Caillén]?mac?Niataig??Crom?mac?Feradaig,?Comgall?mac?Sétnai,?Comgán?mac?Dá?Cherda,?Commán?mac?Fáelchon,?Mo?ChommócCrónán?of?Balla,?see?Mo?Chua?mac?Bécáin',3))

我們得到錯誤......

Ms 1946,Level 16,State 3,Line 45

操作失敗。索引“PK __#B72883F__8E45D1191C112AAE”的長度為980字節的索引條目超過了聚簇索引的最大長度900字節。

結論

sql_variant在用戶表中使用數據類型是一種代碼味道,因為它將非類型化數據類型引入強類型語言,并且需要進行調查,就像您在家聞到燒焦的味道一樣。它可能只是燒烤,但它可能更令人擔憂。

sql_variant 具有合法用途,但總有一種風險,即盡管您可能確切知道如何使用它們,但是其他必須維護或調試代碼的人可能不知道,并且如果您除了純粹使用它們之外做任何其他事情,則最有可能導致問題用于存儲。

你絕不能依賴sql_variant的隱式轉換,因為它經常失敗,要么是因為它沒有實現,要么是因為它是奇怪的。相反,在進行比較、表達式或聚合之前,將它們顯式轉換為SQL數據類型。如果你不完全確定你理解了最后一句話,那么最好永遠不要使用sql_variant。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

昌吉市| 沅江市| 房产| 泽库县| 康保县| 通河县| 潜山县| 乾安县| 延庆县| 山阳县| 衡东县| 彰武县| 托里县| 旌德县| 汉源县| 扎赉特旗| 盘锦市| 咸宁市| 金秀| 奉化市| 英德市| 子洲县| 东乡| 安达市| 讷河市| 红桥区| 鄂托克旗| 和林格尔县| 偏关县| 武清区| 湄潭县| 新化县| 尤溪县| 阿合奇县| 和静县| 红河县| 金门县| 大荔县| 威海市| 辽宁省| 福安市|