T-SQL: как получить точную длину строки в символах? - PullRequest
6 голосов
/ 20 сентября 2010

Я генерирую операторы T-SQL SELECT для таблиц, для которых у меня нет предварительной информации о типе данных. В этих инструкциях мне нужно выполнить операции со строками, которые зависят от длины исходного значения столбцов таблиц.

Одним из примеров (но не единственным) является вставка некоторого текста в определенную позицию в строке, включая возможность вставить его в конце:

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

(CASE WHEN + LEN требуется, потому что STUFF не позволяет мне вставлять текст в конец строки.)

Проблема в том, что LEN исключает конечные пробелы, что разрушит расчет. Я знаю, что могу использовать DATALENGTH, который не исключает конечные пробелы, но я не могу преобразовать байты, возвращаемые DATALENGTH, в символы, требуемые STUFF, потому что я не знаю, имеет ли столбец Product тип varchar или nvarchar.

Итак, как я могу сгенерировать оператор SQL, который зависит от точной длины строки в символах, без предварительной информации об используемом типе данных строки?

Ответы [ 5 ]

13 голосов
/ 23 сентября 2010

Вот что я в итоге использовал:

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

Измерения показывают, что уловка LEN (... + '#') - 1 примерно такая же, как у LEN (...).

Спасибо за все хорошие ответы!

4 голосов
/ 20 сентября 2010

попробуйте это:

SELECT 
  CASE WHEN (LEN (REPLACE([t0].[Product],' ', '#') = 8) 
    THEN [t0].[Product] + 'test' 
    ELSE STUFF ([t0].[Product], 8, 0, 'test') 
  END
FROM [OrderItem] [t0]
3 голосов
/ 20 сентября 2010

Не можете ли вы найти информацию о типе столбцов в системных таблицах?

Если нет, то определить, является ли столбец varchar или nvarchar, это будет сделано.

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
1 голос
/ 20 сентября 2010

Используйте DATALENGTH и SQL_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 голосов
/ 21 июня 2012

Если нет ведущих пробелов, len(reverse(column_name)) даст вам длину столбца.

...