Tôi không biết liệu cách này có nhanh hơn không, nhưng bạn có thể sử dụng một thủ thuật:FOR XML AUTO
sẽ bỏ qua các cột không có nội dung:
DECLARE @tbl TABLE(col1 INT,col2 INT,col3 INT);
INSERT INTO @tbl VALUES (1,2,NULL),(1,NULL,NULL),(NULL,NULL,NULL);
SELECT *
FROM @tbl AS tbl
FOR XML AUTO
Đây là kết quả:col3
bị mất tích ...
<tbl col1="1" col2="2" />
<tbl col1="1" />
<tbl />
Biết được điều này, bạn có thể tìm thấy danh sách các cột không phải là NULL trong tất cả các hàng, như sau:
DECLARE @ColList VARCHAR(MAX)=
STUFF
(
(
SELECT DISTINCT ',' + Attr.value('local-name(.)','nvarchar(max)')
FROM
(
SELECT
(
SELECT *
FROM @tbl AS tbl
FOR XML AUTO,TYPE
) AS TheXML
) AS t
CROSS APPLY t.TheXML.nodes('/tbl/@*') AS A(Attr)
FOR XML PATH('')
),1,1,''
);
SELECT @ColList
Nội dung của @ColList
bây giờ là col1,col2
. Chuỗi này bạn có thể đặt trong SELECT
được tạo động .
CẬP NHẬT:Gợi ý
Sẽ rất thông minh nếu thay thế SELECT *
với danh sách cột được tạo từ INFORMATION_SCHEMA.COLUMNS
loại trừ tất cả not-nullable . Và - nếu cần và có thể - các loại, sẽ chứa dữ liệu rất lớn (BLOB).
CẬP NHẬT2:Hiệu suất
Không biết dữ liệu rất lớn của bạn là gì có nghĩa là thực sự ... Chỉ cần thử điều này trên một bảng có khoảng 500.000 hàng (với SELECT *
) và nó đã trở lại chính xác sau chưa đầy một phút. Hy vọng, điều này đủ nhanh ...