Запрос сравнения дат в SQL

84

У меня есть таблица с датами, которые все происходили в ноябре. Я написал этот запрос

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
created_date <= '2013-04-12'

Этот запрос должен возвращать все, что произошло в 11-м месяце (ноябрь), потому что это произошло до даты «2013-04-12» (в декабре).

Но это только возвращение доступных дат , которые происходили в дни меньше , чем 04 (2013- 04 -12)

Может быть, это всего лишь сравнение дневной части? а не всю дату?

Как это исправить?

Created_date имеет тип date

Формат даты по умолчанию - гггг-дд-мм.

Помощь
источник
1
Вы сравниваете даты со строками, а не с датами,
Панайотис Канавос,
4
Может думает 2013-04-12? 12 апреля? А может быть created_date, это строка, а не дата?
jpw
Посмотрите руководство по Cast & Convert в T-SQL и используйте соответствующее преобразование для вашего региона
Стив,
3
Не нужно вообще приводить, просто используйте неизменяемый формат '20130412'
Панайотис Канавос
1
Вместо того, чтобы отправлять строку с датой, попробуйте создать параметризованный запрос и передать дату как параметр типа даты. Кстати, какую версию SQL Server вы используете? DATE был добавлен в SQL Server 2008.
Панайотис Канавос

Ответы:

84

Вместо «2013-04-12», значение которого зависит от местной культуры, используйте «20130412», который распознается как инвариантный формат языка.

Если вы хотите сравнить с декабря 4 - го , вы должны написать «20131204». Если вы хотите сравнить с апреля 12 - го , вы должны написать «20130412».

В статье « Написание международных операторов Transact-SQL» из документации SQL Server объясняется, как писать операторы, которые не зависят от языка и региональных параметров:

Приложения, использующие другие API-интерфейсы или сценарии Transact-SQL, хранимые процедуры и триггеры, должны использовать неразделенные числовые строки. Например, ггггммдд как 19980924.

РЕДАКТИРОВАТЬ

Поскольку вы используете ADO, лучшим вариантом является параметризация запроса и передача значения даты в качестве параметра даты. Таким образом, вы полностью избегаете проблемы с форматированием и получаете преимущества в производительности параметризованных запросов.

ОБНОВИТЬ

Чтобы использовать формат ISO 8601 в литерале, необходимо указать все элементы. Цитата из раздела ISO 8601 документации datetime

Чтобы использовать формат ISO 8601, вы должны указать каждый элемент в формате. Это также включает T, двоеточия (:) и точку (.), Которые показаны в формате.

... доля второго компонента не обязательна. Компонент времени указывается в 24-часовом формате.

Панайотис Канавос
источник
@andy не совсем так, формат ISO8601 включает элемент времени. Или , как говорят документы , To use the ISO 8601 format, you must specify each element in the format. This also includes the T.
Панайотис Канавос
1
Извините за непонятность, но я хотел сказать, что ISO8601 определяет порядок именно так, как вы описали: ГГГГ-ММ-ДД или для краткости ГГГГММДД. Однако, как говорится в документации: «datetime не соответствует стандартам ANSI или ISO 8601.». Сам ISO не требует временной части.
Энди
Что вы имеете в виду не меняет того факта , что YYYY-MM-DDэто не признанную в качестве ISO 8601. Время детали будут необходимы. Назовите это странностью T-SQL, если хотите, или неполной реализацией. Возможно даже, что это было перенесено из Sybase
Панайотис Канавос
32

Попробуйте вот так

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
created_date <= '2013-12-04'
Нитеш Нараянан
источник
6
Формат, специфичный для культуры. Это 12 апреля или 4 декабря? Формат, разделенный тире, НЕ является международным форматом,
Панайотис Канавос,
1
Так что же происходит, когда вам нужно хранить данные от международных клиентов? Или дата исходит из веб-браузера, который соответствует культуре пользователя ? Руководящие принципы существуют не просто так, и, просто НЕ используя неправильный формат, вы избегаете всех ошибок,
Панайотис Канавос,
1
@Nithesh Это возвращается 12 апреля
HelpASisterOut
19
@PanagiotisKanavos Формат, разделенный тире, является международным форматом с момента публикации ISO 8601 в 1988 году. Другие форматы не одобряются и высмеиваются . Даже опубликованная вами статья «Написание международных операторов Transact-SQL» ни разу не определяет «ггггммдд» как какой-либо «международный» стандарт.
Джесси Уэбб
2
Добавление одинарных кавычек вокруг даты решило эту проблему. Использовал формат 19.02.2015. Поменял на «19.02.2015», и он начал работать. Спасибо за простую идею.
Итан Терк
10

Если Вы сравниваете только с датой юдоли, а затем преобразовать его в актуальном состоянии (не даты и времени ) будет работать

select id,numbers_from,created_date,amount_numbers,SMS_text 
 from Test_Table
 where 
 created_date <= convert(date,'2013-04-12',102)

Это преобразование также применимо во время использования GetDate () функции

Бимзи
источник
4

Ставишь <=и он тоже поймает данную дату. Вы можете заменить его <только на.

Кузгун
источник
2

пожалуйста, попробуйте с запросом ниже

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
convert(datetime, convert(varchar(10), created_date, 102))  <= convert(datetime,'2013-04-12')
Нареш Пансурия
источник
0

Формат даты - гггг-мм-дд. Таким образом, приведенный выше запрос ищет записи старше 12 апреля 2013 г.

Предлагаем вам выполнить быструю проверку, установив строку даты на «2013-04-30», если нет ошибки sql, формат даты подтверждается на гггг-мм-дд.

Боуи
источник
0

Попробуйте использовать "#" до и после даты и убедитесь, что ваш системный формат даты. возможно «ГГГГММДД О ГГГГ-ММ-ДД О ММ-ДД-ГГГГ О ИСПОЛЬЗОВАНИЕ '/ О \'»

Пример:

 select id,numbers_from,created_date,amount_numbers,SMS_text 
 from Test_Table
 where 
 created_date <= #2013-04-12#
Рен Марин
источник