#sql #sql-server #tsql #language-agnostic
Вопрос:
У меня есть столбец в таблице базы данных (SQL Server 2005), содержащий такие данные:
TQ7394
SZ910284
T r1534
su8472
Я хотел бы обновить эту колонку, чтобы первые два символа были прописными. Я также хотел бы удалить любые пробелы между первыми двумя символами. Так T q1234
бы и стало TQ1234
.
Решение должно быть в состоянии справиться с несколькими пробелами между первыми двумя символами.
Возможно ли это в T-SQL? Как насчет ANSI-92? Мне всегда интересно посмотреть, как это делается и в других БД, поэтому не стесняйтесь публиковать ответы для PostgreSQL, MySQL и др.
Комментарии:
1. Что вернет T<пробел><пробел><пробел>Q7394? TQ7394?
2. Хорошая мысль. Несколько пробелов также следует удалить; я обновлю вопрос.
Ответ №1:
Вот решение:
ИЗМЕНИТЬ: Обновлено для поддержки замены нескольких пробелов между первым и вторым символами, не являющимися пробелами
/* TEST TABLE */
DECLARE @T AS TABLE(code Varchar(20))
INSERT INTO @T SELECT 'ab1234x1' UNION SELECT ' ab1234x2'
UNION SELECT ' ab1234x3' UNION SELECT 'a b1234x4'
UNION SELECT 'a b1234x5' UNION SELECT 'a b1234x6'
UNION SELECT 'ab 1234x7' UNION SELECT 'ab 1234x8'
SELECT * FROM @T
/* INPUT
code
--------------------
ab1234x3
ab1234x2
a b1234x6
a b1234x5
a b1234x4
ab 1234x8
ab 1234x7
ab1234x1
*/
/* START PROCESSING SECTION */
DECLARE @s Varchar(20)
DECLARE @firstChar INT
DECLARE @secondChar INT
UPDATE @T SET
@firstChar = PATINDEX('%[^ ]%',code)
,@secondChar = @firstChar PATINDEX('%[^ ]%', STUFF(code,1, @firstChar,'' ) )
,@s = STUFF(
code,
1,
@secondChar,
REPLACE(LEFT(code,
@secondChar
),' ','')
)
,@s = STUFF(
@s,
1,
2,
UPPER(LEFT(@s,2))
)
,code = @s
/* END PROCESSING SECTION */
SELECT * FROM @T
/* OUTPUT
code
--------------------
AB1234x3
AB1234x2
AB1234x6
AB1234x5
AB1234x4
AB 1234x8
AB 1234x7
AB1234x1
*/
Ответ №2:
UPDATE YourTable
SET YourColumn = UPPER(
SUBSTRING(
REPLACE(YourColumn, ' ', ''), 1, 2
)
)
SUBSTRING(YourColumn, 3, LEN(YourColumn))
Ответ №3:
UPPER
это не повредит никаким цифрам, поэтому, если приведенные вами примеры полностью репрезентативны, на самом деле в этом нет никакого вреда:
UPDATE tbl
SET col = REPLACE(UPPER(col), ' ', '')
Ответ №4:
В образцах данных в начале есть только пробелы и строчные буквы. Если это справедливо для реальных данных, то просто:
UPPER(REPLACE(YourColumn, ' ', ''))
Для более конкретного ответа я бы вежливо попросил вас расширить вашу спецификацию, иначе мне пришлось бы кодировать все другие возможности (например, значения менее трех символов), не зная, переоценивал ли я свое решение для обработки данных, которые на самом деле не возникли бы в реальности 🙂
Как всегда, как только вы исправите данные, установите ограничение базы данных, чтобы гарантировать, что плохие данные не повторятся, например
ALTER TABLE YourTable ADD
CONSTRAINT YourColumn__char_pos_1_uppercase_letter
CHECK (ASCII(SUBSTRING(YourColumn, 1, 1)) BETWEEN ASCII('A') AND ASCII('Z'));
ALTER TABLE YourTable ADD
CONSTRAINT YourColumn__char_pos_2_uppercase_letter
CHECK (ASCII(SUBSTRING(YourColumn, 2, 1)) BETWEEN ASCII('A') AND ASCII('Z'));
@huo73: ваш не работает для меня в SQL Server 2008: я получаю «TRr1534» вместо «TR1534».
Комментарии:
1. Мне это нравится, но оно должно заменять только пробелы между первыми двумя символами. Это заменяет все пробелы, которые все еще могут быть полезны для запросов SELECT.
Ответ №5:
update Table set Column = case when len(rtrim(substring (Column , 1 , 2))) < 2
then UPPER(substring (Column , 1 , 1) substring (Column , 3 , 1)) substring(Column , 4, len(Column)
else UPPER(substring (Column , 1 , 2)) substring(Column , 3, len(Column) end
Это работает на том факте, что если есть пробел, то обрезка этой части строки даст длину меньше 2, поэтому мы разделяем строку на три и используем верхний на 1-м и 3-м символах. Во всех остальных случаях мы можем разделить строку на 2 части и использовать верхний регистр, чтобы сделать первые два символа прописными.
Ответ №6:
Если вы выполняете ОБНОВЛЕНИЕ, я бы сделал это в 2 этапа; сначала избавьтесь от пробела (RTRIM на ПОДСТРОКЕ), а во-вторых, сделайте ВЕРХНИЙ на первых 2 символах:
// uses a fixed column length - 20-odd in this case
UPDATE FOO
SET bar = RTRIM(SUBSTRING(bar, 1, 2)) SUBSTRING(bar, 3, 20)
UPDATE FOO
SET bar = UPPER(SUBSTRING(bar, 1, 2)) SUBSTRING(bar, 3, 20)
Если вам это нужно в SELECT (т. Е. встроенном), то у меня возникнет соблазн написать скалярный UDF
Комментарии:
1. Почему бы не использовать REPLACE(строка, ‘ ‘, «) в первом операторе? Таким образом, если в столбце есть несколько пробелов между первой и второй буквой, вы получите и их.
2. Действительно нравится простота и ясность этого.
3. @тост: Я думаю, все сводится к правильной спецификации того, что будет/не будет заменено — в идеале с поддержкой тестовых случаев! Да, есть несколько способов освежевать кошку…