Запит для порівняння дат у SQL


83

У мене є таблиця з датами, що все сталося в листопаді. Я написав цей запит

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)

Можливо, це лише порівняння денної частини? а не цілу дату?

Як це виправити?

Дата_створення має тип дати

Формат дати за замовчуванням рррр-дд-мм


1
Ви порівнюєте дати зі струнами, а не дати з датами
Панайотис Канавос

4
Може це думає 2013-04-12? це 12 квітня? А може created_dateце рядок, а не дата?
jpw

Подивіться на Cast & Convert у посібнику T-SQL та використовуйте відповідне перетворення для вашої мови
Steve

3
Не потрібно взагалі кастувати, просто використовуйте інваріантний формат '20130412'
Панайотис Канавос

1
Замість того, щоб надсилати рядок із датою, спробуйте створити параметризований запит і передайте дату як параметр, введений датою. До речі, яку версію SQL Server ви використовуєте? DATE було додано в SQL Server 2008.
Панайотис Канавос,

Відповіді:


82

Замість "2013-04-12", значення якого залежить від місцевої культури, використовуйте "20130412", який визнано форматом, інваріантним до культури.

Якщо ви хочете порівняти з грудня 4 - го , ви повинні написати «20131204». Якщо ви хочете порівняти з квітня 12 - го , ви повинні написати «20130412».

Стаття Написання міжнародних виписок Transact-SQL з документації SQL Server пояснює, як писати твердження, які інваріантні до культури:

Додатки, які використовують інші API або сценарії Transact-SQL, збережені процедури та тригери, повинні використовувати нерозділені числові рядки. Наприклад, yyyymmdd як 19980924.

РЕДАГУВАТИ

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

ОНОВЛЕННЯ

Щоб використовувати формат ISO 8601 у буквальному виразі, потрібно вказати всі елементи. Цитую з розділу ISO 8601 документації про дату та час

Щоб використовувати формат ISO 8601, потрібно вказати кожен елемент у форматі. Сюди також входять Т, двокрапки (:) та крапка (.), Які відображаються у форматі.

... частка другого компонента необов’язкова. Часова компонента вказана у 24-годинному форматі.


@andy не зовсім так, формат ISO8601 включає елемент часу. Або , як кажуть документи , To use the ISO 8601 format, you must specify each element in the format. This also includes the T.
Panagiotis Kanavos

1
Вибачте за незрозумілість, я хотів сказати, що ISO8601 визначає порядок саме так, як ви описали: РРРР-ММ-ДД або скорочено РРРРММДД. Однак, оскільки в документах також зазначено: "дата-час не відповідає ANSI або ISO 8601.". Сам ISO не потребував би часу.
andy

Що ви маєте в виду не змінює того факту , що YYYY-MM-DDце НЕ визнану в якості ISO 8601. Час деталі будуть необхідні. Назвіть це дивовижністю T-SQL, якщо хочете, або неповною реалізацією. Можливо, навіть це було перенесено з Sybase
Panagiotis Kanavos

31

Спробуйте так

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

6
Формат культури. Це 12 квітня чи 4 грудня? Формат, розділений тире, НЕ є міжнародним форматом
Панайотис Канавос

1
То що трапляється, коли потрібно зберігати дані від міжнародних клієнтів? Або дата поставляється з веб - браузер , який слідує за користувача культуру? Вказівки існують неспроста, і просто НЕ використовуючи неправильний формат, ви уникаєте всіх помилок
Panagiotis Kanavos

1
@Nithesh Це повертається 12 квітня
HelpASisterOut

17
@PanagiotisKanavos Формат, розділений тире, є міжнародним форматом з часів опублікування ISO 8601 у 1988 р. Інші формати не рекомендуються та висміюються . Навіть у статті, яку ви розмістили, "Написання міжнародних заяв Transact-SQL" жодного разу не визначає "yyyymmdd" як будь-який "міжнародний" стандарт.
Джессі Вебб,

2
Додавання одинарних лапок навколо дати вирішило це для мене. Використовував формат 19.02.2015. Змінено на "19.02.2015", і він почав працювати. Дякую за просту ідею.
Ітан Турк

9

Якщо Ви порівнюєте лише з vale дати, тоді перетворення її на дату (а не datetime ) спрацює

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 не буде, формат дати підтверджено yyyy-mm-dd.


0

Спробуйте використовувати "#" до і після дати та переконайтесь у форматі системної дати. можливо "РРРРРММДД О РРРР-ММ-ДД О ММ-ДД-РРРР О ВИКОРИСТАННЯ '/ O \'"

Приклад:

 select id,numbers_from,created_date,amount_numbers,SMS_text 
 from Test_Table
 where 
 created_date <= #2013-04-12#
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.