2010-09-20 47 views
5

Tôi đang tạo các câu lệnh T-SQL SELECT cho các bảng mà tôi không có thông tin kiểu dữ liệu phía trước. Trong các câu lệnh này, tôi cần thực hiện các thao tác chuỗi tùy thuộc vào độ dài của giá trị ban đầu của các cột của bảng.T-SQL: Cách lấy độ dài chính xác của một chuỗi ký tự?

Một ví dụ (nhưng không phải là người duy nhất) là để chèn một số văn bản ở một vị trí cụ thể trong một chuỗi, bao gồm các tùy chọn để chèn nó ở cuối:

SELECT 
    CASE WHEN (LEN ([t0].[Product] = 8) 
    THEN [t0].[Product] + 'test' 
    ELSE STUFF ([t0].[Product], 8, 0, 'test') 
    END 
FROM [OrderItem] [t0] 

(trường hợp khi + LEN là cần thiết vì STUFF không cho phép tôi chèn văn bản vào cuối chuỗi.)

Vấn đề là LEN loại trừ khoảng trắng ở cuối, điều này sẽ làm hỏng phép tính. Tôi biết tôi có thể sử dụng DATALENGTH, không loại trừ khoảng trống cuối, nhưng tôi không thể chuyển đổi các byte được trả về DATALENGTH thành các ký tự do STUFF yêu cầu vì tôi không biết cột Sản phẩm có thuộc loại varchar hay nvarchar hay không. Vì vậy, làm thế nào tôi có thể tạo ra một câu lệnh SQL phụ thuộc vào độ dài chính xác của một chuỗi ký tự mà không có thông tin phía trước về kiểu dữ liệu chuỗi đang được sử dụng? Không.

Trả lời

12

Đây là những gì tôi đã kết thúc bằng:

SELECT 
    CASE WHEN ((LEN ([t0].[Product] + '#') - 1) = 8) 
    THEN [t0].[Product] + 'test' 
    ELSE STUFF ([t0].[Product], 8, 0, 'test') 
    END 
FROM [OrderItem] [t0] 

đo chỉ ra rằng LEN (. .. + '#') - 1 mẹo có tốc độ giống như LEN (...) thôi.

Cảm ơn tất cả các câu trả lời hay!

+0

+1 cho giải pháp hoạt động! –

+0

+1 Đó có thể là một mẹo hữu ích. –

3

Bạn không thể tra cứu thông tin loại cho các cột trong bảng hệ thống?

Nếu không thì để xác định xem cột có phải là varchar hoặc nvarchar điều này sẽ làm điều đó.

create table #test 
(
c varchar(50), 
n nvarchar(50) 
) 

insert into #test values ('1,2,3,4 ',N'1,2,3,4,5  ') 

SELECT 
     CASE 
       WHEN datalength(CAST(c AS nvarchar(MAX))) = datalength(c) 
       THEN 'c is nvarchar' 
       ELSE 'c is char' 
     END, 
     CASE 
       WHEN datalength(CAST(n AS nvarchar(MAX))) = datalength(n) 
       THEN 'n is nvarchar' 
       ELSE 'n is char' 
     END 
FROM #test 
+0

Tra cứu thông tin: có thể có thể, nhưng khó khăn. Tôi cũng không chắc chắn điều này sẽ thực hiện như thế nào. –

+0

Bài kiểm tra cũng thú vị, nhưng tôi nghĩ rằng tôi thích REPLACE hack tốt hơn một chút liên quan đến "khả năng đọc" của câu lệnh kết quả. –

+0

@Fabien - Tôi khá chắc chắn tìm kiếm thông tin loại sẽ hoạt động tốt hơn so với thực hiện thay thế trên mỗi chuỗi trong cột hoặc một chuỗi trên mỗi chuỗi. –

4

thử điều này:

SELECT 
    CASE WHEN (LEN (REPLACE([t0].[Product],' ', '#') = 8) 
    THEN [t0].[Product] + 'test' 
    ELSE STUFF ([t0].[Product], 8, 0, 'test') 
    END 
FROM [OrderItem] [t0] 
+0

Ý tưởng hay, tôi nên tự mình làm điều này ... –

+0

Điều này rất không hiệu quả, như số đo của tôi cho thấy. –

+1

Tuy nhiên, một biến thể nhanh chóng này nhanh như chớp: LEN ([t0]. [Sản phẩm] + '#') - 1 Tốc độ này tương đương với LEN ([t0]. [Sản phẩm]). .. –

1

Sử dụng DATALENGTHSQL_VARIANT_PROPERTY:

SELECT 
    CASE 
    WHEN 8 
     = DATALENGTH([t0].[Product]) 
    /CASE SQL_VARIANT_PROPERTY([t0].[Product],'BaseType') WHEN 'nvarchar' THEN 2 ELSE 1 END 
    THEN [t0].[Product] + 'test' 
    ELSE STUFF ([t0].[Product], 8, 0, 'test') 
    END 
FROM [OrderItem] [t0] 
+0

Tôi đã thử nghiệm này, và trong khi nó trông giống như những gì tôi cần, nó không hoạt động với varchar (max)/nvarchar (max) - bởi vì sql_variant không thể giữ các giá trị như vậy. –

0

Nếu không có khoảng trắng hàng đầu, len(reverse(column_name)) sẽ cung cấp cho bạn độ dài cột.