Как перевести первые буквы каждого слова предложения в верхний регистр?

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

Условия:

  • Слова разделяются единичными пробелами.
  • Количество слов произвольно.

Алгоритм:

  • Разбиваем фразу на отдельные слова, которые помещаем в табличную переменную.
  • Делаем первую букву каждого слова прописной.
  • Собираем строку из слов, соблюдая порядок, с помощью функции STRING_AGG.

Итак, функция:

create or alter function firstBigLetter(@name varchar(max))
returns varchar(max)
as
begin
  declare @i int = 1, @next int = 1;
  declare @t table(id int identity primary key, word varchar(100))
  -- Пока подумаем, зачем нам identity?
  while @next > 0
  begin
    select @next=charindex(' ', @name, @i);
    if @next=0 -- больше пробелов нет, берем последнее слово
      insert into @t(word) select substring(@name, @i, len(@name))
    else -- берем очередное слово между @i и @next
      insert into @t(word) select substring(@name, @i, @next-@i)
    set @i=@next + 1; -- начало следующего слова
  end
  --Выполняем требуемое преобразование слов
  update @t set word= upper(left(word, 1)) + lower(substring(word, 2, len(word)))
  -- Сборка и возврат
  return(select string_agg(word, ' ') 
  WITHIN GROUP (ORDER BY id) -- вот зачем нам Identity!
  from @t)
end;
go
 
-- Вызов
select dbo.firstBigLetter('еСли кто-то кое-ГДе у наС порой');

--Результат
Если Кто-то Кое-где У Нас Порой

Пояснения.

  1. Конструкция CREATE OR ALTER FUNCTION появилась в SQL Server 2017 как аналог CREATE OR REPLACE FUNCTION в PostgreSQL. Теперь не нужно напрягать память, чтобы не забыть поменять ALTER на CREATE после отладки. 🙂
  2. Столбец Identity задает нам порядок, в котором следуют слова в предложении. Поэтому при сборке мы используем сортировку именно по этому столбцу — WITHIN GROUP (ORDER BY id).
  3. Естественно, можно было не выполнять разбивку на слова, а, например, использовать рекурсивный запрос, но я преследовал тут вполне определенные учебные цели. Если кто-то решит оценить производительность различных алгоритмов, можете поделиться результатами в комментариях.

Функция STRING_AGG, которая использовалась при сборке предложения, имеет обратную функцию STRING_SPLIT (обе эти функции появились в SQL Server 2017), которая как раз выполняет разбивку символьной строки, формируя одностолбцовую таблицу. Использование этой функции напрашивается для решения нашей задачи. Однако, согласно документации, она не гарантирует порядка. В моих примерах строка восстанавливалась правильно, поэтому я приведу и это решение в качестве примера использования функции. Но если вы решите применять её, то делайте это на свой страх и риск.:-)

create or alter function firstBigLetterWithoutOrder(@name varchar(max))
returns varchar(max)
as
begin
  return(select string_agg(upper(left(value,1))+lower(substring(value,2,len(value))),' ') from
         (select value from STRING_SPLIT(@name,' ')) X)
end
go

--Вызов
select dbo.firstBigLetterWithoutOrder('еСли кто-то кое-ГДе у наС порой');

Добавить комментарий