淺析SQL數據類型的隱式轉換與顯式轉換以及隱式轉換可能導致的問題


一、隱式類型轉換問題

1、隱式類型轉換:

  比如:SELECT 1 + '1';

2、隱式類型轉換的問題:

(1)程序可讀性差,且依賴數據庫的隱式轉換規則,效率差,會增加處理時間;且如果數據庫升級,則程序可能無法正確執行;

(2)有可能會導致索引失效;

(3)有可能會導致意想不到的結果;

3、顯式類型轉換:SELECT 1 + CAST('1' AS SIGNED INT);

4、原則:盡量用顯式類型轉換

5、隱式轉換問題示例:

(1)數值型 + 字符型

SELECT 1+'1';           -- 結果:2
SELECT CONCAT('北京',2008);    -- 結果:北京2008
SELECT '北京' + 2008;       -- 結果: 可能2008,可能報錯
SELECT 'HELLO ' + 'WORLD!';    -- 結果:可能 0,可能報錯

(2)隱式類型轉換導致索引失效

CREATE TABLE teacher( teacher_id VARCHAR(50), teacher_name VARCHAR(50), id_no VARCHAR(50) ); CREATE INDEX idx_teacher_id ON teacher(teacher_id); CREATE TABLE student( student_id INT, student_name VARCHAR(50), teacher_id INT ); CREATE INDEX idx_teacher_id ON student(teacher_id); SELECT
*
FROM student a INNER JOIN teacher b ON a.teacher_id = b.teacher_id; -- 此時不會走索引,因為在teacher表中,teacher_id是varchar類型,而student表中teacher_id是int類型, -- 會做隱式類型轉換,把varchar轉為int類型;

(3)隱式類型轉換導致意想不到的結果

SELECT 10/4;       -- 結果:2 解決:可以把分母分子乘以1.00,再運算
    
SELECT COUNT(*) FROM table1;    -- count返回的是int類型,如果表中數據量超過count出來的數,就報錯 -- 解決:在count(*) 外面cast轉換一下,轉換為能保存結果的類型
SELECT COUNT(*) FROM teacher WHERE teacher_name = 0; -- 為什么不是等價於:
SELECT COUNT(*) FROM teacher WHERE teacher_name= '0'; -- 因為隱式類型轉換時,轉的是左邊而不是右邊;

-- 以下語句會返回兩條信息,而不是一條,因為530102192005080114這串數字,已經超過了int類型的范圍, -- 超過了int類型的范圍就會轉為float類型,等號兩邊都轉為float類型,會丟精度,也就是最后一位數丟了,剩下的就相等了,就全返回了;

SELECT COUNT(*) FROM teacher WHERE id_no = 530102192005080114; -- 等價於:
SELECT COUNT(*) FROM teacher WHERE 
CAST(id_no AS DECIMAL) = CAST(530102192005080114 AS DECIMAL); -- 在查詢時把530102192005080114加上單引號就可以了;

二、SQL 數據類型轉換

  數據類型轉換分為隱式轉換和顯式轉換。

1、顯式轉換:顧名思義就是使用函數進行數據類型轉化,如cast、convert

2、隱式轉換問題

-- 例子1
SELECT 1+1’ –返回值為2 -- 例子 2
SELECT
CASE
WHEN 1 > 1 THEN 10
WHEN 1 = 1 THEN10WHEN 1 < 1 THEN 10.2
END    -- 返回值為10.2

-- 例子3
SELECT
CASE
WHEN 1 > 1 THEN 10
WHEN 1 = 1 THEN ‘abc’ WHEN 1 < 1 THEN 10.2
END     -- 語法錯誤 

  在第一個例子中,'1' 被轉換為 int 的 1 ;

  在第二個例子中,不管那個后面的條件成立,結果都被轉換為decima;

  第三個例子由於‘ab’轉換為decimal失敗,所以報錯。

  為什么呢?  ——  這是因為 sql server 中有多個數據類型在一個表達式中時會存在隱式的轉換,各個數據類型的優先級如下:

1、用戶定義數據類型(最高) 2、sql_variant 3、xml 4datetime
5smalldatetime
6float
7real
8decimal
9money
10smallmoney
11bigint
12int
13smallint
14tinyint
15bit
16ntext
17text
18image
19timestamp
20uniqueidentifier
21nvarchar(包括 nvarchar(max)) 22nchar
23varchar (包括 varchar(max)) 24char
25varbinary(包括 varbinary(max)) 26binary(最低) 

3、詳細見:數據類型優先級 (Transact-SQL)  ——  https://docs.microsoft.com/zh-cn/previous-versions/sql/sql-server-2005/ms190309(v=sql.90)?redirectedfrom=MSDN

  當兩個不同數據類型的表達式用運算符組合后,數據類型優先級規則指定將優先級較低的數據類型轉換為優先級較高的數據類型。 如果此轉換不是所支持的隱式轉換,則返回錯誤。 當兩個操作數表達式具有相同的數據類型時,運算的結果便為該數據類型。

  這里有一篇文章也說了這個 case when 里的隱式轉換導致的問題,可以看下:《SQL Server有意思的數據類型隱式轉換問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM