Giới thiệu
Hello các bạn. Trong bài viết này mình sẽ chia sẻ cho các bạn biết mốt số câu lệnh hay ho và khá hữu ích trong SQL Server nhé. Cùng bắt đầu nào...
Để phục vụ cho bài viết này mình sẽ sử dụng table Products (như hình dưới) để làm demo nhé. Phần script và dữ liệu của table này mình sẽ để ở cuối bài cho bạn nào cần.

1. Clone, Copy hoặc Duplicate Table
Chắc hẳn các bạn đã gặp trường hợp muốn Clone một table nào đó từ một table có sẵn trong database và đôi khi là clone toàn bộ Data sang một table mới với stucture hoàn toàn giống nhau hay chỉ thay đổi tên column mà vẫn dữ nguyên cấu trúc như data type đúng không?
Và các bạn sẽ sử dụng câu lệnh CREATE hay sử dụng Generate Script Table đó? Khá dài dòng và phức tạp đúng không? Mình có cách đơn giản hơn đó :D. Cùng xem nhé!
SELECT * FROM Products INTO ProductDetail WHERE 1 = 0
Câu lệnh trên mình đã thực hiện Clone toàn bộ structure của table Products sang table ProductDetail. Đoạn script trên hoàn toàn không clone theo Data từ table Products, các bạn muốn clone cả Data thì sửa điều kiện WHERE ở trên nhé!
SELECT ProductId AS Id, Name, Status FROM Products INTO ProductDetail2 WHERE 1 = 0
Ở đoạn script này mình thực hiện việc clone các column ProductId, Name, Status sang một table mới có tên ProductDetail2. Điều chú ý ở đây là mình không clone column Info và thực hiện đổi tên ProductId sang Id nhưng vẫn giữ nguyên stucture của các column được clone. Lúc này table ProductDetail2 sẽ có các column Id, Name, Status
2. SELECT kết hợp CASE WHEN
SELECT
[ProductId],
[Name]
[Info],
[Status],
CASE
WHEN [Status] = 1 THEN N'Đã thanh toán'
WHEN [Status] = 2 THEN N'Chưa thanh toán'
ELSE N'Lỗi'
END AS ProductStatus
FROM Products
Output của câu lệnh trên như sau:

Như các bạn thấy việc sử dụng CASE WHEN rất đa năng trong việc Query và đôi lúc bạn sẽ cần đến nó trong câu Query của mình
3. Sử dụng SQL đông với "sp_executesql"
Khi bạn cần viết một Store Procedure hoặc thực hiện một câu Query thông thường, trong đó tùy thuộc vào giá trị của các tham số đầu vào mà câu lệnh SQL cần thực hiện sẽ thay đổi, bạn cần tạo lập chuỗi lệnh SQL trong chương trình và thực thi chuỗi này. Chuỗi lệnh SQL đó được gọi là sql động. Ví dụ khi có một tham số vào qui định tên bảng cần được truy vấn; hoặc khi bạn có một đoạn sql code lưu trữ trong database (như một biểu thức tính toán hoặc mệnh đề WHERE…) và bạn cần ghép vào thành một lệnh SQL hoàn chỉnh để thực thi.
Giải thích hơi dài dòng nhỉ. Cùng đi vào thực tế nào...
DECLARE @SqlQuery NVARCHAR(MAX) = ''
DECLARE @Status INT = 1
SET @SqlQuery = 'SELECT
[ProductId],
[Name]
[Info],
[Status]
FROM Products'
IF(@Status = 1)
BEGIN
SET @SqlQuery += ' WHERE [Status] = 1'
END
--------------------------------------------------------
ELSE IF(@Status = 2)
BEGIN
SET @SqlQuery += ' WHERE [Status] = 2'
END
--------------------------------------------------------
ELSE IF(@Status = 3)
BEGIN
SET @SqlQuery += ' WHERE [Status] = 3'
END
EXEC sp_executesql @SqlQuery
Kết quả sau khi thực thi đoạn script trên:

Như các bạn thấy ở trên thì mình có một câu lệnh truy vấn được gán trong biến @SqlQuery. Và dựa vào các điều kiện @Status mà mình thực hiện cộng chuỗi truy vấn đó với điều kiện WHERE tương ứng. Kết quả sau khi thực hiện ở dòng EXEC sp_executesql @SqlQuery sẽ cho kết quả theo câu lệnh truy vấn @SqlQuery. Các bạn có thể dùng PRINT @SqlQuery để xem câu lệnh hoàn chỉnh được thực thi.
Ngoài cách truy vấn trên chúng ta hoàn toàn có thể thêm các Parameter vào trong câu truy vấn với sp_executesql như sau:
DECLARE @SqlQuery NVARCHAR(MAX) = ''
DECLARE @Parameters NVARCHAR(MAX) = '@Status INT, @Value NVARCHAR(255)'
SET @SqlQuery = 'SELECT
[ProductId],
[Name]
[Info],
[Status],
@Value AS Text
FROM Products
WHERE [Status] = @Status'
EXEC sp_executesql @SqlQuery, @Parameters, @Status = 2, @Value = 'Code Mega'
Kết quả của câu lệnh trên sẽ là:

4. STRING_AGG
STRING_AGG dùng để nối các giá trị của chuỗi với sự trợ giúp của các dấu phân tách trong khi không thêm dấu phân tách ở cuối chuỗi. Dữ liệu đầu vào có thể là VARCHAR, NVARCHAR, bạn có thể tùy ý chỉ định thứ tự hiển thị của kết quả bằng việc sử dụng mệnh đề WITHIN GROUP.
SELECT
STRING_AGG([Name], ' | ') WITHIN GROUP (ORDER BY ProductId ASC)
FROM Products
WHERE [Status] = 1
GROUP BY [Status]
Hàm này thực sự rất bá đạo và rất hữu ích cho các bạn trong tương lai nên nhơ thực hành nó nhiều nhé!
5. INSERT Data bằng SELECT
DECLARE @TempTable TABLE (
[ProductId] INT,
[ProductName] NVARCHAR(MAX),
[Status] INT
)
INSERT INTO @TempTable
(
[ProductId],
[ProductName],
[Status]
)
SELECT
[ProductId],
[Name],
[Status]
FROM dbo.Products
WHERE [Status] = 1
SELECT * FROM @TempTable
Ở trên mình đã thực hiện tạo một biến table @TempTable và tiến hành INSERT dữ liễu từ bảng Products với điều kiện Status = 1. Với câu lệnh trên mình có thể thực hiện INSERT một cách linh hoạt với câu lệnh SELECT cực kỳ hữu dụng.
6. Multi Update với JSON
DECLARE @ProductIds NVARCHAR(MAX) = '[1,2,3]'
DECLARE @TableProductIds TABLE (
[Id] INT
)
INSERT INTO @TableProductIds SELECT CAST(I.Value AS BIGINT) AS Id FROM OPENJSON(@ProductIds) I WHERE I.Value IS NOT NULL
UPDATE P
SET P.Status = 1
FROM dbo.Products AS P
INNER JOIN @TableProductIds AS T
ON T.Id = P.ProductId
WHERE 1 = 1
SELECT * FROM Products WHERE ProductId IN(1,2,3)
Ở trên mình có một chuỗi @ProductIds. Mình sử dụng hàm OPENJSON để Cast dữ liệu từ chuỗi ra dạng JSON, cụ thể ở đây là Array Json và INSERT vào @TableProductIds. Tiếp đó là thực hiện Update Status trong Products thành 1. Việc thực hiện Update kiểu như này sẽ giúp chúng ta tiết kiện thời gian và dễ dàng hơn khi thực hiện chuỗi Update cùng một kết quả mà không cần dùng vòng lặp. Performance từ đó cũng tốt hơn.
7. Phân Trang (Paging SQL)
DECLARE @PageNumber = 1
DECLARE @PageSize = 10
DECLARE @Offset INT = (@PageNumber - 1) * @PageSize
SELECT * FROM dbo.Products
ORDER BY ProductId
OFFSET @Offset ROWS
FETCH NEXT @PageSize ROWS ONLY
@PageNumber
: Số trang
@PageSize
: Số sản phẩm sẽ được hiển thị mỗi trang
@Offset
: Được tính toán để xác định hàng bắt đầu cho trang hiện tại. Công thức (@PageNumber - 1) * @PageSize
tính toán độ lệch dựa trên số trang và kích thước trang. Ví dụ: trên trang 2 (@PageNumber = 2
) với kích thước trang là 10 (@PageSize = 10
), độ lệch sẽ là (2 - 1) * 10 = 10
, cho biết kết quả nên bắt đầu từ hàng thứ 11 (vì lập chỉ mục bắt đầu từ 1).
Kết Luận
Hi vọng những chia sẻ trên sẽ giúp ích được cho các bạn. Nếu có thắc mắc hãy để lại comment nhé. Cám ơn các bạn đã theo dõi. 😉