функція прийому символу введення та формату дати повернення (з неправильним вводом)


9

Мені потрібно написати функцію для отримання символу рядка та повернення формату дати. Наприклад, введення є 20120101, і мені потрібен цей 2012-01-01. Проблема полягає в тому, що можуть бути деякі некоректні вводи, як-от "2012ABCD". У такому випадку я хочу, щоб функція повертала фіксовану дату, таку як 2020-01-01. Що я писав поки що:

Create Function ReturnDate
(@date varchar(8))

Returns date

  as

    begin
       declare @result date

          set @result = (select convert(date , @date,111))
                if(@@ROWCOUNT>0) return @result
                 else return '2020-01-01'
       return @result
    end

Це не працює, і я просто не знаю, як обробити другу частину (коли введення невірно).


1
Я можу порекомендувати вам прочитати "Запит даних за допомогою Transact-SQL" Якщо ви будете робити багато програм SQL, ця книга навчить вас основ кодування таких речей. amazon.com/Exam-70-761-Querying-Data-Transact-SQL-ebook/dp/…
Tony

1
Ви хочете суворого розбору yyyymmddформату?
Дан Гузман

Відповіді:


9

На SQL Server 2012 та пізніших версіях ви можете використовувати TRY_CONVERT, щоб перевірити, чи можна перетворити вхід. Якщо це не вдається, повертається значення NULL, тож ви можете зробити COALESCE, щоб отримати перетворене значення або фіксовану дату.

begin
   declare @result date
   set @result = COALESCE(TRY_CONVERT(date, @date, 111), '2012-01-01')
   return @result
end

Ви також можете використовувати TRY CATCHблок і повернути фіксовану дату в CATCHблоці, але найкраще використовувати TRY_CONVERT, щоб SQL Server не мав обробляти помилку, оскільки для цього потрібно більше часу та ресурсів.

Функція для цього типу коду матиме більше накладних витрат, ніж просто використання однієї і тієї ж логіки у запиті, тому, якщо вона викликається багато разів щосекунди, ви можете жувати значний ресурс, використовуючи функцію для цього. Я розумію, що це може бути викликано з численних фрагментів коду, тому є бажання зробити його функцією у випадку, якщо дату за замовчуванням потрібно змінити - тоді це не змінений код, а просто оновіть цю функцію.

Якщо цей код буде запускатися багато, слід розглянути інші варіанти, які забезпечать кращу продуктивність, ніж визначена користувачем функція. Будь ласка, дивіться відповідь Соломона для огляду ваших варіантів та подальшого пояснення, чому ви можете вибрати один над іншим.

Наприклад, нижче показано таку ж логіку, що реалізована як функція вбудованої таблиці, яка має бути використана, CROSS APPLYякщо вона не надається статичним значенням, але працює набагато краще, ніж скалярний UDF:

USE [tempdb];

GO
CREATE
OR ALTER -- comment out if using pre-SQL Server 2016 SP1
FUNCTION dbo.ReturnDate (@Date VARCHAR(8))
RETURNS TABLE
AS RETURN
  SELECT ISNULL(TRY_CONVERT(DATE, @Date, 111), '2020-01-01') AS [TheDate];
GO


SELECT *
FROM   (VALUES (1, '20120101'), (2, '2012ABCD')) tab(ID, Input)
CROSS APPLY dbo.ReturnDate(tab.[Input]) dt
/*
ID    Input       TheDate
1     20120101    2012-01-01
2     2012ABCD    2020-01-01
*/

6
Але я просто використовую TRY_CONVERT у запиті та відкидаю всю ідею використання неефективного скалярного АДС для цього ...
Аарон Бертран

2
Я не дуже переймаюся питаннями повторень, тому я не кажу про це через втрату таких, але громада не отримує користі від того, щоб негативно відповідати на відповідь. Замість того, щоб схилятись, напишіть відповідь, відредагуйте шахту або залиште коментар щодо того, що потрібно змінити. ОП попросив функцію, і я розумію, що це може бути не найкращим рішенням, але саме рішення було запропоновано.
Тоні Хінкл

3
Тоні: Я не проголосував, але я, безумовно, погоджуюся, що хтось не повинен брати участь в голосуванні, не надаючи міркування в коментарі, або підсумовуючи існуючий коментар, що включає їх міркування. Це сказало: 1)FINALLY в T-SQL немає блоку (я думаю, ви це мали на увазі CATCH). 2) вам, мабуть, слід згадати, що TRY_CONVERTрозпочався в 2012 році (деякі люди застрягли перед SQL Server 2012). 3) Ви розглядали Inline TVF? Вони не мають тих самих проблем щодо ефективності, як у скалярних АДС.
Соломон Руцький

1
@TonyHinkle Дякую за внесення змін та за посилання на мою відповідь "Так" :). Але я не впевнений, скільки читачів зможе зробити стрибок від того, щоб побачити логіку UDF і прочитати, що вбудований TVF буде кращим, до успішної реалізації iTVF. Отже, я пішов вперед і додав це до кінця вашої відповіді.
Соломон Руцький

1
@SolomonRutzky Дякую Я насправді не розробник SQL, тому все ще над головою. Можливо, я не повинен відповідати на щось подібне, але це надзвичайна можливість навчання.
Тоні Хінкл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.