Trước hết, bạn không thể làm gì nếu không có chúng, phải không?
Chuyển đổi dữ liệu SQL hay cụ thể hơn là chuyển đổi kiểu dữ liệu là một phần thiết yếu trong công việc lập trình thường xuyên của nhà phát triển cơ sở dữ liệu hoặc DBA.
Bây giờ, điều gì sẽ xảy ra nếu sếp của bạn ký hợp đồng với một công ty khác để cung cấp cho họ một tệp ở định dạng văn bản đến từ cơ sở dữ liệu SQL Server của bạn?
Điều này nghe có vẻ như một thử thách thú vị!
Nhưng bạn phát hiện ra rằng bạn sẽ phải xử lý ngày thành chuỗi, số thành chuỗi và một loạt các chuyển đổi dữ liệu SQL khác. Bạn vẫn sẵn sàng cho thử thách?
Không phải không có kho thủ thuật chuyển đổi dữ liệu của bạn!
Có gì sẵn có ngoài hộp?
Khi tôi lần đầu tiên bắt đầu lập trình T-SQL, điều đầu tiên tôi thấy phù hợp với mục đích chuyển đổi là CHUYỂN ĐỔI () hàm.
Ngoài ra, từ "chuyển đổi" có phải không?
Mặc dù điều này có thể đúng, nhưng đó chỉ là một trong 4 cách để thực hiện công việc này. Và tôi đã sử dụng nó cho gần như TẤT CẢ chuyển đổi dữ liệu SQL của mình. Tôi rất vui vì tôi đã vượt qua điều đó. Vì tôi đã biết rằng 4 phương pháp có vị trí riêng trong mã của bạn.
Trước khi chúng ta đi đến chủ đề của bài đăng, hãy để tôi trình bày 4 phương pháp đơn giản để thực hiện chuyển đổi dữ liệu SQL:
- CAST ()
- CHUYỂN ĐỔI ()
- PARSE ()
- TRY_CAST (), TRY_CONVERT (), TRY_PARSE ()
Mỗi phần bên dưới sẽ:
- Giải thích nó là gì
- Cho bạn biết khi nào sử dụng nó (các trường hợp sử dụng)
- Trình bày những hạn chế của nó
- Đưa ra các ví dụ và giải thích nó
Mọi thứ được trình bày trong bài viết này đều bằng tiếng Anh đơn giản, dễ hiểu nhất có thể. Khi bạn đọc xong toàn bộ bài đăng, bạn sẽ biết phương pháp nào phù hợp với một tình huống nhất định.
Vì vậy, không cần phải quảng cáo gì thêm, chúng ta hãy đi sâu vào.
1. Chuyển đổi dữ liệu SQL bằng CAST ()
Mặc dù tất cả các phương pháp bạn sẽ thấy đều có thể chuyển đổi kiểu dữ liệu, nhưng lựa chọn đầu tiên của bạn khi chuyển đổi chắc chắn phải là CAST ().
Đây là những lý do tại sao:
- Đây là chức năng chuyển đổi chạy nhanh nhất trong số tất cả. Chúng tôi sẽ cố gắng chứng minh điều này sau trong bài đăng này.
- Nó được bao gồm trong các tiêu chuẩn đặc tả ngôn ngữ SQL-92. Vì vậy, khi bạn cần chuyển mã của mình sang các sản phẩm SQL khác, như MySQL, chức năng này cũng có sẵn.
Đây là cú pháp rất đơn giản cho CAST ():
CAST( <expression> AS <data_type>[(length)] )
Đầu tiên, hãy kiểm tra cú pháp:
- < biểu thức > là bất kỳ biểu thức hợp lệ nào dẫn đến giá trị có thể được chuyển đổi thành kiểu dữ liệu đích.
- < data_type > là kiểu dữ liệu đích.
- chiều dài là tùy chọn và nó liên quan đến kích thước của dữ liệu.
Sử dụng nó khi nào
Nếu điều duy nhất bạn cần là chuyển đổi một giá trị sang một kiểu dữ liệu khác, thì CAST () chỉ là những gì bạn cần.
Giới hạn
Về mặt tiêu cực, CAST () không thể cung cấp cho bạn đầu ra có định dạng giống như giá trị ngày và giờ được định dạng.
Ví dụ
A. Chuyển đổi một chuỗi thành một ngày:
SELECT CAST('09/11/2004 4:30PM' as datetime2)
Và chạy câu lệnh trên sẽ dẫn đến:
B. Chuyển đổi một số thành một chuỗi:
SELECT CAST(10.003458802 as varchar(max))
Và kết quả của sự chuyển đổi trên là:
Bây giờ, nếu bạn cần một cái gì đó khác như định dạng dữ liệu đã chuyển đổi, thì phương pháp tiếp theo có thể giúp bạn.
2. Chuyển đổi dữ liệu SQL bằng CONVERT ()
Tùy chọn chuyển đổi dữ liệu tiếp theo là sử dụng CONVERT (). Như tôi đã nói trước đây, đây là cái mà tôi đã sử dụng nhiều nhất trong những ngày trước đó.
Đây là cú pháp:
CONVERT( <data_type>[(length)], <expression> [, <style>])
Từ cú pháp trên, hãy lưu ý rằng < style > tham số là tùy chọn. Và trừ khi bạn cung cấp, chức năng sẽ tương tự như CAST ().
Đó là nơi tôi bắt đầu bối rối khi tôi mới làm quen với SQL.
Sử dụng nó khi nào
Nếu bạn chuyển đổi dữ liệu với định dạng tức thì thì CHUYỂN ĐỔI () là bạn của bạn. Có nghĩa là bạn đối xử với < phong cách > tham số đúng.
Hạn chế
- CAST () nhanh hơn CONVERT (), vì vậy nếu bạn chỉ cần chuyển đổi dữ liệu, hãy sử dụng CAST (). Nếu đầu ra phải được định dạng, hãy sử dụng CHUYỂN ĐỔI ().
- CHUYỂN ĐỔI () không phải là một tiêu chuẩn SQL-92, vì vậy nếu bạn cần chuyển nó sang RDBMS khác, hãy tránh sử dụng nó.
Ví dụ
A. Chuyển đổi ngày sang định dạng chuỗi yyyymmdd
Trong ví dụ sau, tôi sẽ sử dụng cơ sở dữ liệu mẫu AdventureWorks và chuyển đổi [ Ngày bắt đầu ] cột thành yyyymmdd :
USE AdventureWorks
GO
SELECT
[BillOfMaterialsID]
,CONVERT(varchar(10), [StartDate],112) as StartDate
FROM [Production].BillOfMaterials]
GO
Lưu ý rằng kiểu 112 được sử dụng để định dạng ngày thành yyyymmdd .
B. Chuyển một số thành chuỗi có dấu phẩy ở mỗi 3 chữ số ở bên trái dấu thập phân.
Tương tự, ví dụ sau sẽ minh họa AdventureWorks cơ sở dữ liệu mẫu và chúng tôi sẽ định dạng số bằng dấu phẩy và 2 chữ số thập phân.
USE AdventureWorks
GO
SELECT
[TransactionID]
,[ProductID]
,CONVERT(varchar(10),[TransactionDate] ,112) as StartDate
,[Quantity]
,CONVERT(varchar(10),[ActualCost],1) as ActualCost
FROM [Production].TransactionHistory
GO
Lưu ý rằng định dạng 1 được sử dụng cho [ Chi phí thực tế ]. Và cảm ơn CONVERT (), chúng tôi có thể định dạng các cột này ngay lập tức.
Tuy nhiên, điều gì sẽ xảy ra nếu bạn cần chuyển đổi một biểu thức ngày dài hơn? Sẽ CHUYỂN ĐỔI () làm việc trong trường hợp đó? Đọc để tìm hiểu về phương pháp tiếp theo.
3. Chuyển đổi dữ liệu SQL bằng PARSE ()
Phương pháp tiếp theo mà chúng tôi sẽ xem xét là PARSE ().
Kiểm tra cú pháp:
PARSE( <string value> AS <datatype> [USING <culture>])
Sử dụng nó khi nào
- Để chuyển đổi chuỗi thành ngày tháng hoặc số sử dụng một nền văn hóa cụ thể.
- Khi không thể chuyển đổi chuỗi thành ngày hoặc số bằng CAST () hoặc CHUYỂN ĐỔI (). Xem các ví dụ để biết thêm thông tin.
Hạn chế
- Chỉ có thể chuyển đổi chuỗi thành ngày tháng và chuỗi thành số
- Dựa vào sự hiện diện của .Net Framework Common Language Runtime (CLR) trên máy chủ.
- Không có trong thông số kỹ thuật tiêu chuẩn của SQL-92, vì vậy việc chuyển sang các RDBMS khác là một vấn đề.
- Có chi phí hiệu suất khi phân tích chuỗi.
Ví dụ
A. Chuyển đổi chuỗi ngày dài
SELECT PARSE('Monday, June 8, 2020' as datetime USING 'en-US')
Ví dụ ở trên là một chuỗi ngày dài được chuyển đổi thành ngày giờ giá trị sử dụng văn hóa tiếng Anh của Mỹ. Và đây là nơi PARSE () sẽ cố gắng hết sức.
Đó là vì mã ở trên sẽ không thành công nếu bạn sử dụng CAST () hoặc CHUYỂN ĐỔI ().
B. Chuyển đổi giá trị tiền bằng ký hiệu tiền tệ
SELECT PARSE('€1024,01' as money using 'de-DE')
Bây giờ, hãy thử thực hiện chuyển đổi bằng CAST () và CHUYỂN ĐỔI ()
SELECT CONVERT(money,'€1024,01')
SELECT CAST('€1024,01' as money)
Tuyên bố sẽ không có lỗi, tuy nhiên, hãy xem kết quả bất ngờ này:
Do đó, giá trị đã được chuyển đổi thành 102401,00 thay vì 1024,01.
Cho đến nay, chúng tôi đã phát hiện ra rằng 3 phương pháp đầu tiên rất dễ bị lỗi trừ khi bạn kiểm tra chúng. Tuy nhiên, phương pháp thứ 4 có thể là giải pháp cho kết quả bị lỗi.
4. Chuyển đổi dữ liệu SQL sử dụng TRY_CAST (), TRY_CONVERT () hoặc TRY_PARSE ()
Cuối cùng, phương pháp cuối cùng để chuyển đổi dữ liệu SQL là sử dụng một biến thể của 3 phương pháp đầu tiên nhưng có tiền tố là TRY_.
Nhưng ngay cả như vậy, sự khác biệt là gì?
Chúng có cùng tham số với 3 tham số trước đó mà không có tiền tố TRY_. Nhưng sự khác biệt là, chúng trả về NULL nếu giá trị không thể được chuyển đổi. Bây giờ, nếu giá trị không thể được chuyển đổi rõ ràng bởi bất kỳ giá trị nào trong số 3, thì sẽ xảy ra lỗi. Xem các ví dụ bên dưới để hiểu rõ hơn.
Sử dụng nó khi nào
Bạn có thể sử dụng bất kỳ câu nào trong số 3 câu lệnh có điều kiện như CASE KHI NÀO hoặc IIF để kiểm tra lỗi.
Hạn chế
3 trong số chúng có những hạn chế giống như những cái không có tiền tố TRY_, ngoại trừ các giá trị không thể chuyển đổi.
Ví dụ
A. Sử dụng TRY_CAST () để kiểm tra xem chuyển đổi có thành công hay không khi sử dụng IIF:
SELECT IIF(TRY_CAST('111b' AS real) IS NULL, 'Cast failed', 'Cast succeeded') AS Result
Đoạn mã trên sẽ trả về "Truyền không thành công" vì không thể chuyển đổi "111b" thành thực . Loại bỏ "b" khỏi giá trị và nó sẽ trả về "Đã truyền thành công".
B. Sử dụng TRY_CONVERT () vào các ngày có định dạng cụ thể
SET DATEFORMAT dmy;
SELECT TRY_CONVERT(datetime2, '12/31/2010') AS Result
Điều này sẽ trả về NULL vì định dạng sử dụng dmy hoặc ngày-tháng-năm. Và biểu thức đầu vào cho TRY_CONVERT () ở định dạng mdy hoặc tháng-ngày-năm. Lỗi được kích hoạt vì giá trị tháng là 31.
C. Sử dụng TRY_PARSE () sẽ tạo ra lỗi thời gian chạy
SELECT
CASE WHEN TRY_PARSE('10/21/2133' AS smalldatetime USING 'en-US') IS NULL
THEN 'True'
ELSE 'False'
END AS Result
Đoạn mã này sẽ tạo ra lỗi thời gian chạy như bên dưới:
Đó là đối với 4 phương pháp đơn giản trong chuyển đổi dữ liệu SQL. Nhưng còn nhiều điều sắp xảy ra.
Làm thế nào về Chuyển đổi dữ liệu SQL bằng cách sử dụng chuyển đổi ngầm?
Bây giờ chúng ta hãy xem xét chuyển đổi ngầm định. Đây là một phương pháp im lặng.
Tại sao lại im lặng?
Bởi vì bạn có thể đã làm điều đó, nhưng bạn không biết về nó. Hoặc ít nhất, bạn biết điều đó đang xảy ra, nhưng bạn đang phớt lờ nó.
Nói cách khác, đây là kiểu chuyển đổi mà SQL tự động thực hiện mà không cần bất kỳ chức năng nào.
Để tôi cho bạn một ví dụ:
DECLARE @char CHAR(25)
DECLARE @varchar VARCHAR(25)
DECLARE @nvarchar NVARCHAR(25)
DECLARE @nchar NCHAR(25)
SET @char = 'Live long and prosper'
SET @varchar = @char
SET @nvarchar = @varchar
SET @nchar = @nvarchar
SELECT @char AS [char], @varchar AS [varchar], @nvarchar AS [nvarchar], @nchar AS [nchar]
Đoạn mã trên sẽ được thực thi thành công. Hãy tự mình thử và bạn sẽ có kết quả tương tự như bên dưới:
Hãy thử điều này với các ngày:
DECLARE @datetime datetime
DECLARE @smalldatetime smalldatetime
DECLARE @datetime2 datetime2
SET @datetime = '12/31/2050 14:34'
SET @smalldatetime = @datetime
SET @datetime2 = @smalldatetime
SELECT @datetime as [datetime], @smalldatetime as [smalldatetime], @datetime2 as [datetime2]
Như mong đợi, điều này sẽ mang lại kết quả thành công:
Hãy thử nó lần này với các con số:
DECLARE @int int
DECLARE @real real
DECLARE @decimal decimal
DECLARE @float float
SET @int = 1701
SET @real = @int
SET @decimal = @real
SET @float = @decimal
SELECT @int as [int], @real as [real], @decimal as [decimal], @float as [float]
Vẫn là một thành công, phải không?
Cho đến nay, chúng tôi đã sử dụng các giá trị đơn giản sẽ phù hợp với một loại dữ liệu khá giống nhau. Hãy chuyển sang cấp độ tiếp theo:số thành chuỗi.
DECLARE @number int
DECLARE @string varchar(5)
SET @number = 1701
SET @string = @number
SELECT @number as [number], @string as [string]
Điều này sẽ được chuyển đổi thành công như bạn có thể thấy từ kết quả bên dưới:
Có nhiều trường hợp khác khi SQL Server sẽ cố gắng “đoán” cách chuyển đổi dữ liệu. Như bạn có thể thấy từ tài liệu tham khảo này, có nhiều trường hợp so với các trường hợp yêu cầu chuyển đổi rõ ràng.
Vì SQL Server cho phép điều này, điều này có nghĩa là bạn có thể tự do cho phép điều này xảy ra trên toàn bộ mã của mình?
Cảnh báo trong chuyển đổi ngầm định
Đối với một điều, nó có thể thuận tiện. Nhưng khi đạt đến giới hạn của từng loại dữ liệu, bạn sẽ nhận ra rằng chuyển đổi ngầm định hơi nguy hiểm nếu không được chọn.
Hãy xem xét một ví dụ dưới đây:
DECLARE @char char(25)
DECLARE @varchar varchar(25)
DECLARE @nvarchar nvarchar(25)
DECLARE @nchar nchar(25)
SET @nvarchar = N'I ❤ U!'
SET @nchar = @nvarchar
SET @char = @nchar
SET @varchar = @nchar
SELECT @char as [char], @varchar as [varchar], @nvarchar as [nvarchar], @nchar as [nchar]
Bạn có thấy giá trị của biểu tượng cảm xúc không? Đó sẽ được tính là một giá trị unicode.
Mặc dù tất cả các câu lệnh ở trên sẽ chạy thành công, nhưng các biến có loại không phải unicode như varchar và char sẽ có kết quả bất ngờ. Xem kết quả bên dưới:
Tuy nhiên, đó không phải là vấn đề duy nhất. Lỗi sẽ xuất hiện khi giá trị nằm ngoài phạm vi. Hãy xem xét một ví dụ với ngày tháng:
DECLARE @datetime datetime
DECLARE @smalldatetime smalldatetime
DECLARE @datetime2 datetime2
SET @datetime = '12/31/2374 14:34'
SET @smalldatetime = @datetime
SET @datetime2 = @smalldatetime
SELECT @datetime as [datetime], @smalldatetime as [smalldatetime], @datetime2 as [datetime2]
Việc chỉ định ngày giờ giá trị của smalldatetime biến sẽ gây ra lỗi như bạn có thể thấy bên dưới:
Nhưng có một lưu ý khác mà bạn cũng nên biết khi xử lý chuyển đổi ngầm:chi phí hiệu suất. Thấy rằng đây là một chủ đề nóng, rất đáng để có một chuyên mục riêng.
Hàm ý về hiệu suất của các phương pháp chuyển đổi dữ liệu SQL khác nhau
Bạn có tin hay không, các phương pháp chuyển đổi dữ liệu SQL khác nhau sẽ có hiệu suất khác nhau trong các tình huống thực tế. Và ít nhất bạn nên nhận thức được điều này để có thể tránh được những cạm bẫy về hiệu suất.
Cách CAST (), CONVERT () và PARSE () thực hiện
Trước tiên, hãy kiểm tra cách CAST (), CHUYỂN ĐỔI () và PARSE () thực hiện trong điều kiện tự nhiên bằng cách so sánh cái nào nhanh hơn. Chúng tôi thích nghi và chứng minh khái niệm về ví dụ của chúng tôi được lấy từ đây. Hãy xem xét đoạn mã dưới đây:
USE AdventureWorks
GO
SET STATISTICS TIME ON
SELECT CAST([NationalIDNumber] as int) FROM [HumanResources].[Employee]
SELECT CONVERT(int,[NationalIDNumber]) FROM [HumanResources].[Employee]
SELECT PARSE([NationalIDNumber] as int) FROM [HumanResources].[Employee]
SET STATISTICS TIME OFF
GO
Bây giờ, hãy kiểm tra mã sử dụng AdventureWorks cơ sở dữ liệu từ Microsoft:
- BẬT THỜI GIAN THỐNG KÊ sẽ xuất ra thời gian CPU và thời gian đã trôi qua trong mỗi CHỌN tuyên bố
- Sau đó, cột chúng tôi chọn để chuyển đổi cho mục đích trình diễn là [ NationalIDNumber ], có loại nvarchar (15) .
- Ngoài ra, chuyển đổi từ một chuỗi thành một số nguyên: nvarchar (15) thành int .
- Và cuối cùng, chúng tôi khôi phục ĐẶT THỜI GIAN THỐNG KÊ về giá trị trước đó của nó
Lưu ý kết quả đầu ra trong Tin nhắn tab của kết quả Truy vấn:
Dưới đây là những gì chúng tôi đã đưa ra bằng cách sử dụng ví dụ này:
- Điều đó chứng tỏ rằng CAST () hoạt động nhanh nhất (1 mili giây) và PARSE () hoạt động chậm nhất (318 mili giây).
- Chúng tôi tuân theo mức độ ưu tiên này khi quyết định sử dụng chức năng nào để chuyển đổi dữ liệu:( 1 ) ĐÚC () ( 2 ) CHUYỂN ĐỔI () ( 3 ) PARSE ().
- Ghi nhớ thời điểm phù hợp của từng chức năng và cân nhắc các hạn chế khi quyết định sử dụng chức năng nào.
Cách chuyển đổi ngầm thực hiện
Tại thời điểm này, bạn sẽ có thể thấy rằng tôi khuyên bạn nên sử dụng các hàm như CAST () để chuyển đổi dữ liệu. Và trong phần này, bạn sẽ thấy tại sao.
Xem xét truy vấn này bằng cách sử dụng WideWorldImporters cơ sở dữ liệu từ Microsoft. Trước khi thực hiện, vui lòng bật Bao gồm kế hoạch thực thi thực tế trong SQL Server Management Studio .
USE WideWorldImporters
GO
SELECT
[CustomerID]
,[OrderID]
,[OrderDate]
,[ExpectedDeliveryDate]
FROM [Sales].[Orders]
WHERE [CustomerID] like '487%'
Trong truy vấn ở trên, chúng tôi lọc kết quả của các đơn hàng bán hàng với [ ID khách hàng ] như '487%'. Việc này chỉ là để chứng minh tác dụng của việc chuyển đổi ngầm định của một int loại dữ liệu có trên varchar .
Tiếp theo, chúng tôi kiểm tra kế hoạch thực hiện bên dưới:
Như bạn có thể thấy, có một cảnh báo trong CHỌN biểu tượng. Do đó, hãy di chuột để xem chú giải công cụ. Tiếp theo, hãy chú ý đến thông báo cảnh báo, cụ thể là CONVERT_IMPLICIT .
Trước khi chúng tôi tiếp tục, CONVERT_IMPLICIT này cảnh báo xảy ra khi cần thực hiện chuyển đổi ngầm định cho SQL Server. Chúng ta hãy xem xét kỹ hơn vấn đề. Như mô tả bên dưới, cảnh báo có 2 phần:
- CONVERT_IMPLICIT có thể ảnh hưởng đến "CardinalityEstim" trong lựa chọn kế hoạch truy vấn.
- CONVERT_IMPLICIT có thể ảnh hưởng đến “SeekPlan” trong lựa chọn kế hoạch truy vấn.
Cả hai đều chỉ ra rằng truy vấn của bạn sẽ chạy chậm hơn. Nhưng chúng tôi biết tại sao, tất nhiên. Chúng tôi cố tình buộc chuyển đổi ngầm bằng cách sử dụng LIKE toán tử cho một giá trị số nguyên.
Vấn đề ở đây là gì?
- Chuyển đổi dữ liệu ngầm định khiến SQL Server sử dụng CONVERT_IMPLICIT , điều này làm chậm quá trình thực thi truy vấn của bạn.
- Để khắc phục sự cố này, hãy loại bỏ việc sử dụng chuyển đổi ngầm định. Trong trường hợp của chúng tôi, chúng tôi đã sử dụng [ CustomerID ] THÍCH '487%', chúng tôi có thể khắc phục bằng cách thay đổi [ ID khách hàng ] =487. Việc sửa truy vấn sẽ thay đổi kế hoạch thực thi truy vấn, loại bỏ cảnh báo trước đó và thay đổi toán tử quét chỉ mục thành tìm kiếm chỉ mục. Cuối cùng, hiệu suất được cải thiện.
Kết thúc có hậu? Vâng!
Bài học rút ra
Như đã trình bày, chúng tôi không thể để SQL Server thực hiện chuyển đổi với một chuyển đổi ngầm định. Tôi khuyên bạn nên tuân theo thứ tự ưu tiên khi quyết định sử dụng gì khi chuyển đổi dữ liệu.
- Trước tiên, nếu bạn chỉ cần chuyển đổi nguyên trạng, hãy sử dụng CAST (). Đây là một chức năng được chuẩn hóa hơn khi liên quan đến việc chuyển sang các RDBM khác.
- Thứ hai, nếu bạn cần dữ liệu được định dạng, hãy sử dụng CONVERT ().
- Thứ ba, nếu cả CAST () và CHUYỂN ĐỔI () không thực hiện được công việc, hãy sử dụng PARSE ().
- Cuối cùng, để kiểm tra lỗi khi chuyển đổi, hãy sử dụng TRY_CAST (), TRY_CONVERT () hoặc TRY_PARSE ().
Tốt, đó là tất cả cho bây giờ. Tôi hy vọng điều này sẽ giúp bạn trong cuộc phiêu lưu mã hóa tiếp theo của bạn. Gãy chân!
Để tìm hiểu thêm về chủ đề chuyển đổi dữ liệu SQL từ Microsoft:
- ĐÚC và CHUYỂN ĐỔI
- PARSE
- TRY_CAST, TRY_CONVERT và TRY_PARSE