Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.141.47.221] |
|
Данный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ. |
Сообщ.
#1
,
|
|
|
На своём компе поставил MS SQL Server и в запросах из делфей использую следующий формат дат: yyyy-mm-dd, все работает, переношу прогу на другой компьютер, где в свою очередь, тоже стоит MS SQL Server с этой же базой, при попытке сделать запрос вылетает исключение - мол не могу конвертнуть дату, если же исправить формат даты на dd.mm.yyyy, то все пашет, но дома у меня так не работает. Короче, если кто-нить что-нить понял, объясните мне пожалуйста, как сделать "универсальный" формат даты?
|
Сообщ.
#2
,
|
|
|
Универсальный формат - "YYYYMMDD HH:MM:SS".
Ещё можно использовать команду "SET DATEFORMAT". В качестве аргумента передаётся "mdy", "ymd". А потом задавать дату в программе в соответствующем формате. Но эта команда действительна только внутри текущего коннекта. |
Сообщ.
#3
,
|
|
|
Цитата Lector @ 30.12.04, 11:35 Универсальный формат - "YYYYMMDD HH:MM:SS". Короче у меня на компе работает, а на другом нет! Там прокатывают даты только в формате dd.mm.yyyy, почему? Может это от языка зависит? |
Сообщ.
#4
,
|
|
|
самы безапасныи вариант, ползоватся параметрами.
можно восползоватся функциеи FormatDateTime('YYYYMMDD', Date) или в запросе восползоватся функциеи select CONVERT(varchar, GETDATE(), 112) |
Сообщ.
#5
,
|
|
|
Цитата Kobra @ 30.12.04, 12:55 самы безапасныи вариант, ползоватся параметрами. можно восползоватся функциеи FormatDateTime('YYYYMMDD', Date) Таки я ей и пользуюсь. У меня работает, а на другом компе - нет! |
Сообщ.
#6
,
|
|
|
ползуишся параметрами или ишеш в запрос отформатированую дату?
покажи код |
Сообщ.
#7
,
|
|
|
Цитата Kobra @ 30.12.04, 15:32 ползуишся параметрами или ишеш в запрос отформатированую дату? Шлюв запрос отформатированную дату. StrFmt(pszSQLQuery, 'select val, DateM from INTCELL where (DateM >= ''%s'' and DateM <= ''%s'') ' + 'and (%s) and (CounterId = %d) ORDER BY DateM ASC', [FormatDateTime('yyyy.mm.dd', dtpBegin.DateTime), FormatDateTime('yyyy.mm.dd', dtpEnd.DateTime), pszCells, lbCounters.ItemIndex + 1]); |
Сообщ.
#8
,
|
|
|
А DateSeparator у вас не разный ?
|
Сообщ.
#9
,
|
|
|
Цитата Bas @ 30.12.04, 16:04 А DateSeparator у вас не разный ? А кто его знает? Где это посмотреть? |
Сообщ.
#10
,
|
|
|
FormatDateTime('yyyymmdd', dtpBegin.DateTime) но честно сказать с параметрами работать на много безапаснее, тем более когда дело касается дат. так что я бы сделал так: pszSQLQuery.Close; pszSQLQuery.SQL.Clear; pszSQLQuery.SQL.Add('select val, DateM'); pszSQLQuery.SQL.Add('from INTCELL'); pszSQLQuery.SQL.Add('where DateM >= :D1 and DateM <= :D2'); pszSQLQuery.SQL.Add('and ' + pszCells + ' and CounterId = :P2' ); pszSQLQuery.SQL.Add('ORDER BY DateM ASC'); pszSQLQuery.ParamByName('D1').Value := dtpBegin.DateTime; pszSQLQuery.ParamByName('D2').Value := dtpEnd.DateTime; ... pszSQLQuery.ParamByName('P2').Value := lbCounters.ItemIndex + 1; pszSQLQuery.Open; pszCells - не понял что ето такое, так что написал как написал Добавлено кстати ету часть Цитата лудше писать такDateM >= :d1 and DateM <= :d2 Цитата DateM BETWEEN :d1 and :d2 |
Сообщ.
#11
,
|
|
|
pszSQLQuery и pszCells это у меня PChar'ы Ладно смысл понял, сейчас попробую...
Добавлено 1. У меня делфи говорит, что у ADOQuery нет метода ParamByName, по-идеи нужно привести его к TQuery, но хрен его знает как это делать на делфи, я на С++ пишу в основном. 2. Есть ли разница в использовании методов Open()/Close() и свойства Active? 3. Цитата Kobra @ 30.12.04, 16:40 кстати ету часть Цитата DateM >= :d1 and DateM <= :d2 лудше писать такЦитата DateM BETWEEN :d1 and :d2 Почему? Я так раньше писал, но мне больше нравиться когда видно включены ли границы интервала или нет. |
Сообщ.
#12
,
|
|
|
1.
ADOQuery.Parameters.ParamByName() 2. разницы нет. просто когда даю команду пишу Open/Close а когда проверяю открит или нет Active 3. BETWEEN быстрее. а так дело хазяиское |
Сообщ.
#13
,
|
|
|
Цитата Kobra @ 30.12.04, 18:00 3. BETWEEN быстрее. а так дело хазяиское А пачему и на скока? |
Сообщ.
#14
,
|
|
|
Цитата .alex @ 30.12.04, 18:34 А пачему и на скока? наверное потому что ета одна команда, подточенная под свою задачу, а не два. честно говоря не тестировал |
Сообщ.
#15
,
|
|
|
Цитата .alex @ 30.12.04, 08:53 1. У меня делфи говорит, что у ADOQuery нет метода ParamByName, по-идеи нужно привести его к TQuery, но хрен его знает как это делать на делфи, я на С++ пишу в основном. Примерно так: (это лучше чем использование строк) pszSQLQuery.Close; pszSQLQuery.SQL.Clear; pszSQLQuery.SQL.Add('select val, DateM'); pszSQLQuery.SQL.Add('from INTCELL'); pszSQLQuery.SQL.Add('where DateM >= :D1 and DateM <= :D2'); pszSQLQuery.SQL.Add('and ' + pszCells + ' and CounterId = :P2' ); pszSQLQuery.SQL.Add('ORDER BY DateM ASC'); pszSQLQuery.Parameters.ParseSQL(pszSQLQuery.SQL.text, true); pszSQLQuery.Parameters.ParamByName('D1').Value := dtpBegin.DateTime; pszSQLQuery.Parameters.ParamByName('D2').Value := dtpEnd.DateTime; ... pszSQLQuery.Parameters.ParamByName('P2').Value := lbCounters.ItemIndex + 1; pszSQLQuery.Open; |
Сообщ.
#16
,
|
|
|
Цитата Vit @ 31.12.04, 15:25 Примерно так: (это лучше чем использование строк) Я так собственно и сделал, но! Проблема, как выяснилось не решилась - на домашнем компьютере работает, а на чужом нет - вылетает исключение из-за формата даты! |
Сообщ.
#17
,
|
|
|
Цитата .alex,2.01.05, 18:08 @ на домашнем компьютере работает, а на чужом нет - вылетает исключение из-за формата даты! глянуть можешь на удаленном компе Язык и региональные стандарты -> Формат даты и сравнить у себя? |
Сообщ.
#18
,
|
|
|
Цитата Lavrik,2.01.05, 14:44 @ глянуть можешь на удаленном компе Язык и региональные стандарты -> Формат даты и сравнить у себя? Дело в том, что у меня есть доступ только к sql server'y, а про формат даты смогу узнать только числа 10ого Неужели нет какого-нибудь универсального способа? |
Сообщ.
#19
,
|
|
|
Можно установить у себя в проге нужный формат.
DateSeparator='.'; ShortDateFormat="dd.mm.yyyy"; Добавлено Цитата .alex,2.01.05, 14:04 @ Неужели нет какого-нибудь универсального способа Передавать как число. |
Сообщ.
#20
,
|
|
|
Цитата Bas,2.01.05, 15:55 @ Можно установить у себя в проге нужный формат. DateSeparator='.'; ShortDateFormat="dd.mm.yyyy"; ОК, проверю. Цитата Bas,2.01.05, 15:55 @ Передавать как число. Это как? Типа тип данных не datetime, а просто целочисленный сделать? |
Сообщ.
#21
,
|
|
|
Может использовать CONVERT , особое внимание на третий параметр. Нелпа нет так что взглянуть негде
|
Сообщ.
#22
,
|
|
|
тут чтото другое.
когда квери получает дату как параметр, пример из моеи проги ADOQuery1.Close; ADOQuery1.SQL.Clear; ADOQuery1.SQL.Add('SELECT Gacdena.PerID, VPerson.person, VPerson.gankofileba, Gacdena.DateOn, Gacdena.DateOff, Gacdena.Mizezi, '); ADOQuery1.SQL.Add('Gacdena.BNumber, Gacdena.BSeries, Gacdena.BDateOn, Gacdena.BDateOff, Gacdena.Biuletini, Gacdena.Doctor, '); ADOQuery1.SQL.Add('Gacdena.Clinic, DATEDIFF(DD, Gacdena.DateOn, Gacdena.DateOff) + 1 AS Interval, Metka.PerID AS PerID1'); ADOQuery1.SQL.Add('FROM Gacdena INNER JOIN VPerson ON Gacdena.PerID = VPerson.perID LEFT OUTER JOIN Metka ON Gacdena.PerID = Metka.PerID'); ADOQuery1.SQL.Add('WHERE Gacdena.DateOff IS NOT NULL AND Gacdena.DateOn <= :DTP2 AND Gacdena.DateOff >= :DTP1'); ADOQuery1.SQL.Add('ORDER BY Metka.PerID DESC, VPerson.person, Gacdena.DateOn'); ADOQuery1.Parameters.ParamByName('DTP1').Value := DTP1.Date; ADOQuery1.Parameters.ParamByName('DTP2').Value := DTP2.Date; ADOQuery1.Open sp_executesql N'SELECT Gacdena.PerID, VPerson.person, VPerson.gankofileba, Gacdena.DateOn, Gacdena.DateOff, Gacdena.Mizezi, Gacdena.BNumber, Gacdena.BSeries, Gacdena.BDateOn, Gacdena.BDateOff, Gacdena.Biuletini, Gacdena.Doctor, Gacdena.Clinic, DATEDIFF(DD, Gacdena.DateOn, Gacdena.DateOff) + 1 AS Interval, Metka.PerID AS PerID1 FROM Gacdena INNER JOIN VPerson ON Gacdena.PerID = VPerson.perID LEFT OUTER JOIN Metka ON Gacdena.PerID = Metka.PerID WHERE Gacdena.DateOff IS NOT NULL AND Gacdena.DateOn <= @P1 AND Gacdena.DateOff >= @P2 ORDER BY Metka.PerID DESC, VPerson.person, Gacdena.DateOn ', N'@P1 datetime,@P2 datetime', '20050103 00:00:00:000', '20050101 00:00:00:000' исходя из етого, если в программе нписано pszSQLQuery.Parameters.ParamByName('D1').Value := dtpBegin.DateTime у меня смутные подозрения на счет того, что гдето тип данных не DateTime а чтото другое, и соответственно в том месте не правилно производится конвертация. .alex устонави на тои, чужои машине делфи, и в пошаговом режиме погляди все переобразования. |
Сообщ.
#23
,
|
|
|
Цитата Kobra,3.01.05, 10:13 @ .alex устонави на тои, чужои машине делфи, и в пошаговом режиме погляди все переобразования. Незя... Цитата Kobra,3.01.05, 10:13 @ проблем не далжно быть, так как dtpBegin.DateTime тоже автоматически генерирует система. у меня смутные подозрения на счет того, что гдето тип данных не DateTime а чтото другое, и соответственно в том месте не правилно производится конвертация. Может проблема, в том что я использую свойство DateTime, а не Date у TDateTimePicker'a? Просто когда я переносил базу, я сначала экспортировал её в access'вскую, а потом обратно импортировал в ms sql, может в процессе экспорта/импорта поменялся тип данных поля DateM? У меня сейчас нет возможности проверить, но ваще такое возможно? |
Сообщ.
#24
,
|
|
|
Цитата .alex,3.01.05, 17:57 @ Может проблема, в том что я использую свойство DateTime, а не Date у TDateTimePicker'a? если в своистве Time TDateTimePicker-а стоит "0" то резултат только дата, а если чтото другое - то дата время, так что ета без разницы. протестируи, сам увидиш. Цитата .alex,3.01.05, 17:57 @ с аксесом не знаком, но что значит не могу проверить? кто мешает на своем компе протестировать аналогичную ситуацию?У меня сейчас нет возможности проверить, но ваще такое возможно? и вообше, почему Цитата .alex,3.01.05, 17:57 @ на том компе установить своии штуки для тестировки? извени, у меня такого ограничения не бывало и не понемаю смысл. Незя... |
Сообщ.
#25
,
|
|
|
Цитата Kobra,4.01.05, 09:47 @ кто мешает на своем компе протестировать аналогичную ситуацию? Проверю, просто тогда не мог. Цитата Kobra,4.01.05, 09:47 @ и вообше, почему Цитата (.alex @ 3.01.05 17:57) на том компе установить своии штуки для тестировки? извени, у меня такого ограничения не бывало и не понемаю смысл. Я устанавливал свои штуки не на том компе, на котором стоит сервер, а на другом, который находиться с ним в сети, а делфи я на сервере поставить не могу! Цитата Kobra,3.01.05, 10:13 @ и когда он связан с SQL Server-ом запрос передает так, я скопировал запрос из профаилера Где находится этот профайлер? |
Сообщ.
#26
,
|
|
|
профаилер можно вызвать из ентерпраиз менеджера. ето одна из сервисних програм SQL Server-а. чтото на подобии борландовского SQL Monitor-а.
|
Сообщ.
#27
,
|
|
|
Короче профайлер после моего запроса: (где pszCells - это строка вида: CELLId = 1 OR CELLId = 2 OR CELLId = 3, dtpBegin и dtpEnd - это объекты класса TDateTimePicker, а lbCounters - это объект класса TListBox)
SQL.Add('SELECT val, DateM FROM INTCELL WITH (NOLOCK)'); SQL.Add('WHERE (DateM >= :D1 AND DateM <= :D2) AND (' + pszCells + ')'); SQL.Add('AND (CounterId = :P1) ORDER BY DateM ASC'); Parameters.ParamByName('D1').Value := dtpBegin.DateTime; Parameters.ParamByName('D2').Value := dtpEnd.DateTime; Parameters.ParamByName('P1').Value := lbCounters.ItemIndex + 1; показывает следующий запрос: exec sp_executesql N'SELECT val, DateM FROM INTCELL WITH (NOLOCK) WHERE (DateM >= @P1 AND DateM <= @P2) AND (CELLId = 1 OR CELLId = 2 OR CELLId = 3) AND (CounterId = @P3) ORDER BY DateM ASC ', N'@P1 datetime,@P2 datetime,@P3 int', 'Dec 17 2004 10:27PM', 'Dec 24 2004 10:27PM', 1 Что-то я не понимаю почему он так извращает дату. И ещё, почему-то перестало работать условие: (DateM >= :D1 AND DateM <= :D2) Все данные у меня записаны на 18 число декабря 2004г, раньше выборка работала правильно, а теперь только если я ставлю начало интервала, т.е. dtpBegin, на 17 число. Добавлено И исчё! Зачем нужно: pszSQLQuery.Parameters.ParseSQL(XXX, true); |
Сообщ.
#28
,
|
|
|
на месте
dtpBegin.DateTime dtpBegin.Date Цитата Kobra,4.01.05, 09:47 @ а ты передаеш и дату и время, соответственно если в своистве Time TDateTimePicker-а стоит "0" то резултат только дата 'Dec 18 2004 10:27PM' в лубом случае болше 'Dec 18 2004' и выборки нет. 'Dec 17 2004 10:27PM' в лубом случае менше 'Dec 18 2004' и выборки нормалная. pszSQLQuery.Parameters.ParseSQL(XXX, true); Цитата .alex,5.01.05, 17:01 @ он приводит дату в тот вид, какои нравится на SQL Server-у. Что-то я не понимаю почему он так извращает дату. как время убереш, наверняка заработает. вроде запрос правилно передается. |
Сообщ.
#29
,
|
|
|
Цитата Kobra,5.01.05, 18:06 @ а ты передаеш и дату и время, соответственно 'Dec 18 2004 10:27PM' в лубом случае болше 'Dec 18 2004' и выборки нет. 'Dec 17 2004 10:27PM' в лубом случае менше 'Dec 18 2004' и выборки нормалная. Понял. Цитата Kobra,5.01.05, 18:06 @ если в своистве Time TDateTimePicker-а стоит "0" то резултат только дата Изменил DateTime на Date и поставил в свойстве Time у обоих TDateTimePicker - 0:00:00. Все равно передаётся вместе с датой и время: exec sp_executesql N'SELECT val, DateM FROM INTCELL WITH (NOLOCK) WHERE (DateM >= @P1 AND DateM <= @P2) AND (CELLId = 1) AND (CounterId = @P3) ORDER BY DateM ASC ', N'@P1 datetime,@P2 datetime,@P3 int', 'Dec 18 2004 12:00AM', 'Dec 24 2004 12:00AM', 1 Цитата Kobra,5.01.05, 18:06 @ ето харошыи тон, лично я почти никогда не пишу так как ета орерация всеравно выполняется. Я тоже сначала так подумал, но после того как посмотрел в профайлер, решил спросить, ибо когда я ставлю эту строчку: SQL.Add('SELECT val, DateM FROM INTCELL WITH (NOLOCK)'); SQL.Add('WHERE (DateM >= :D1 AND DateM <= :D2) AND (' + pszCells + ')'); SQL.Add('AND (CounterId = :P1) ORDER BY DateM ASC'); Parameters.ParseSQL(SQL.Text, TRUE); Parameters.ParamByName('D1').Value := dtpBegin.Date; Parameters.ParamByName('D2').Value := dtpEnd.Date; Parameters.ParamByName('P1').Value := Integer(lbCounters.Items.Objects[lbCounters.ItemIndex]); дата приводиться к float exec sp_executesql N'SELECT val, DateM FROM INTCELL WITH (NOLOCK) WHERE (DateM >= @P1 AND DateM <= @P2) AND (CELLId = 1) AND (CounterId = @P3) ORDER BY DateM ASC ', N'@P1 float,@P2 float,@P3 int', 3.833900000000000e+004, 3.834500000000000e+004, 1 Это нормально? |
Сообщ.
#30
,
|
|
|
'Dec 18 2004 12:00AM' ето настроики такие и потому, если перефразировать получится "18,12,2004 00:00:00" так что ето не страшно.
Цитата .alex,5.01.05, 18:19 @ веть дата-время хранится как число, так что система сама определяет в каком виде для него будет удобнее получить данные. ето нормално. дата приводиться к float протести такои вариант Parameters.ParamByName('D1').Value := StrToDate(datetostr(dtpBegin.Date)); |
Сообщ.
#31
,
|
|
|
Короче при помощи параметров проблему решить не удалось, решил так:
SET DATEFORMAT ymd А потом в запрос вставлял дату отформатированную под формат 'yyyy-mm-dd', и все... |