C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Работа со временем, запись в БД
Лена
Отправлено: 05.10.2006, 10:57


Мастер участка

Группа: Участник
Сообщений: 501



В базе данных есть поле определенное как время:
stime time NOT NULL, записи в нем храниться в виде 10:00:00
Задала для поля маску __:__:__ пишу в нем без ошибок, например 18:00:00 и всегда получаю исключение на прилагаемом рисунке при попытке ApplyUpdates(-1).
Не совсем понятно, о чем это исключение говорит о каких-то временных зонах?
Обработчик OnSetText также не работает:
CODE

void __fastcall TDataModule2::ClientDataSetRuleetimeSetText(TField *Sender,
const AnsiString Text)
{
try{
TDateTime dtDate = StrToTime(Text); // проверка на формат времени
ClientDataSetRuleetime->AsDateTime = dtDate;
}
catch(...)
{
ShowMessage("Введите правильно время");
//Abort();
}
}

Как, в моем случае, послать запись содержащую только время, в базу?

Отредактировано Лена — 05.10.2006, 11:00

Присоединить изображение

Присоединить изображение

olegenty
Отправлено: 05.10.2006, 11:47


Ветеран

Группа: Модератор
Сообщений: 2412



для начала попробуй

и Ruleetime неплохо, чтобы было TTimeField

CODE

try
{
   TTime ttTime = StrToTime(Text); // проверка на формат времени
   ClientDataSetRuleetime->AsDateTime = ttTime;
} catch(...)
{
              ShowMessage("Введите правильно время");
              //Abort();
}
Лена
Отправлено: 05.10.2006, 12:30


Мастер участка

Группа: Участник
Сообщений: 501



Исключение не пропало.
Что-то видимо с этой таблицей и ее связями в базе или еще что. Любое редактирование столбцов с любыми данными в них приводит к исключению при попытке ApplyUpdates(-1); В самой базе значения могу менять в этой таблице, а у себя в гриде после редактирования и перехода курсора на другую запись исключение. Я ничего не удаляю, просто например, меняю в колонке цифру и получаю это исключение.
sad.gif
В каком направлении искать ошибку?



Присоединить изображение

Присоединить изображение

Admin
Отправлено: 05.10.2006, 12:45


Владимир

Группа: Администратор
Сообщений: 1190



Так это уже другой вопрос, не связанный со временем ?
Со временем все исправилось ?

---
Может попробовать
UpdateMode = upWhereKeyOnly в TDataSetProvider

http://www.delphikingdom.com/asp/answer.as...?IDAnswer=28103
QUOTE

Если в таблице есть ключевое поле, то необходимо указать его в SqlQuery (ProviderFlags = pfInKey), остальным полям убрать флаг pfInWhere. Провайдеру указать UpdateMode = upWhereKeyOnly. Если же ключевого поля нет, то придется "помучаться" с указанием полей, у которых ProviderFlags установить в pfInWhere. Никаким текстовым полям pfInWhere устанавливать нельзя.
Лена
Отправлено: 05.10.2006, 13:13


Мастер участка

Группа: Участник
Сообщений: 501



>Со временем все исправилось ?

Нет, не исправилось. Со временем сначала первое исключение на рисунке, потом второе. Рисунки выше. Если модифицировать запись в колонке, где просто цифры int то тогда просто второе исключение.

Спасибо за дополнительную информацию. Буду разбираться. rolleyes.gif

olegenty
Отправлено: 05.10.2006, 13:16


Ветеран

Группа: Модератор
Сообщений: 2412



с EhLib давно бы уже всё сделала.
Лена
Отправлено: 05.10.2006, 13:17


Мастер участка

Группа: Участник
Сообщений: 501



Попробывала: UpdateMode = upWhereKeyOnly в TDataSetProvider
пока исключение:


Присоединить изображение

Присоединить изображение

Лена
Отправлено: 05.10.2006, 13:19


Мастер участка

Группа: Участник
Сообщений: 501



>с EhLib давно бы уже всё сделала.

Не дают использовать другие компоненты. sad.gif
Я уже пять таблиц оформила, почти закончила. Шестая таблица не поддается. Буду копать. smile.gif


CREATE TABLE rights
(
id int4 NOT NULL DEFAULT nextval('rights_id_seq'::regclass),
gate_id int4 NOT NULL,
group_id int4 NOT NULL,
dweek int2 NOT NULL, -- день недели, 0 — воскр
stime time NOT NULL,
etime time NOT NULL,
CONSTRAINT rights_pk PRIMARY KEY (id)
)
WITHOUT OIDS;
ALTER TABLE rights OWNER TO postgres;
COMMENT ON COLUMN rights.dweek IS 'день недели, 0 — воскр';

Отредактировано Лена — 05.10.2006, 13:22
Admin
Отправлено: 05.10.2006, 13:25


Владимир

Группа: Администратор
Сообщений: 1190



QUOTE
Попробывала: UpdateMode = upWhereKeyOnly в TDataSetProvider пока исключение


Так еще определитесь с ключевыми полями в таблице, ключевому
полю в свойстве ProviderFlags: pfInKey = true,
остальным полям — pfInWhere = false (ну естественно им pfInKey = false)

P.S. Как раз это исключение и сообщает, что в таблице
не задано ключевое поле. Значит верной дорогой идем, товарищи.

Для указанной таблицы rights это получается поле id.
olegenty
Отправлено: 05.10.2006, 13:29


Ветеран

Группа: Модератор
Сообщений: 2412



а так?
CODE

try
{
  TTime ttTime = StrToTime(Text); // проверка на формат времени
  ClientDataSetRuleetime->AsString = Text;
} catch(...)
{
             ShowMessage("Введите правильно время");
             //Abort();
}
Admin
Отправлено: 05.10.2006, 13:38


Владимир

Группа: Администратор
Сообщений: 1190



QUOTE
>с EhLib давно бы уже всё сделала.


Думаю, что с olegenty и Admin тоже всё получиться. biggrin.gif
Лена
Отправлено: 05.10.2006, 14:17


Мастер участка

Группа: Участник
Сообщений: 501



>Думаю, что с olegenty и Admin тоже всё получиться

biggrin.gif biggrin.gif biggrin.gif




>а так?

Не помогло. Меняю пару цифр, например в часах, щелкаю мышью на другой строке и как только доходит до ApplyUpdates(-1) (смотрю через точки останова), то получаю первое исключение с временными зонами. Наверное это связано с общей пробемой обновления этой таблицы.

>ProviderFlags: pfInKey = true,

Я могу добраться до этого свойства в редакторе полей ClientDataSet или ADOQuery. Где лучше установить это свойство или без разницы?


>Как раз это исключение и сообщает, что в таблице
не задано ключевое поле.


А разве эта запись в базе не создает ключевое поле: PRIMARY KEY (id) ?
Все таблицы вроде однородны по структуре. Почему-то проблема именно с этой при редактировании.
Почему эти манипуляции c ProviderFlags мне не потребовались с другими таблицами? Например с этой:
CREATE TABLE gates
(
id int4 NOT NULL DEFAULT nextval('gates_id_seq'::regclass),
name varchar(50) NOT NULL,
enabled bool NOT NULL,
CONSTRAINT pk_gates PRIMARY KEY (id)
)
WITHOUT OIDS;
ALTER TABLE gates OWNER TO postgres;

Может мне надо во всех таблицах установить ProviderFlags для ключевых полей?
Admin
Отправлено: 05.10.2006, 14:43


Владимир

Группа: Администратор
Сообщений: 1190



QUOTE
Не помогло. Меняю пару цифр, например в часах, щелкаю мышью на другой строке и как только доходит до
......
получаю первое исключение с временными зонами. Наверное это связано с общей пробемой обновления этой таблицы.


Не думаю. Скорее не связано.
Тут надо смотреть, с какой строчки кода идет это исключение.
Может формат 00:00:00 в базе вовсе не означает
часы:минуты:секунды ?
Посмотрите ещё окно настроек соединения, там вроде есть еще
Page2, может тоже как формат времени задается ?
Может попробовать еще
так:
ClientDataSetRuleetime->Value = Text;
и так:
TTime ttTime = StrToTime(Text); // проверка на формат времени
ClientDataSetRuleetime->Value = ttTime;
и предварительно посмотрите,
1/ что в Text — например задав ShowMessage(Text); ?
2/ проверьте, какой тип поля имеет поле Ruleetime ?

QUOTE
Я могу добраться до этого свойства в редакторе полей ClientDataSet или ADOQuery. Где лучше установить это свойство или без разницы?


Честно говоря, не знаю. Попробуйте и там и там.
Но второе исключение должно исчезнуть.
Admin
Отправлено: 05.10.2006, 14:58


Владимир

Группа: Администратор
Сообщений: 1190



И какой SQL-запрос изменения значений в таблице ?
(ADOQuery делает только Select, а каким образом идет
изменение данных Update — код ?)
Может в этом SQL-запросе какая-то бяка связанная с этим полем ?
Select CAST(stime as time) from ...
Admin
Отправлено: 05.10.2006, 15:22


Владимир

Группа: Администратор
Сообщений: 1190



Поскольку c PostgreSQL не знаком:
Может реально в базе данные типа time хранятся в формате 000000,
а двоеточия показываются лишь при отображении данных ?

Может тогда так:

CODE

try
{
 TTime ttTime = StrToTime(Text); // проверка на формат времени
 AnsiString s = Text;
 s.Delete(s.Pos(":"),1);  s.Delete(s.Pos(":"),1);
 ClientDataSetRuleetime->AsString = s;
или
 ClientDataSetRuleetime->AsDateTime = s;
}...

Лена
Отправлено: 05.10.2006, 15:52


Мастер участка

Группа: Участник
Сообщений: 501



Спасибо.
Исключение номер два пропало. Можно в двух словах объяснить, почему манипуляции с ProviderFlags необходимы были в этой таблице? Почему я не устанавливала это свойство для других таблиц и там все работало?



Осталось проблема с редактированием времени.
Для всех таблиц у меня просто в ADOQuery записано select * from таблица. Других SQL запросов нет. Обновление записано так:
void __fastcall TDataModule2::ClientDataSetRuleAfterPost(TDataSet *DataSet)
{
ClientDataSetRule->ApplyUpdates(-1);
}

Поле имеет тип TTimeField (вижу в инспекторе объектов).
В точке останова вижу, что строка ClientDataSetRuleetime->Value = Text равна 19:12:00
Строка TTime ttTime = StrToTime(Text); возвращает {val: 0.8}, а исключение возникает в событии:
void __fastcall TDataModule2::ClientDataSetRuleAfterPost(TDataSet *DataSet)
{
ClientDataSetRule->ApplyUpdates(-1);
}

Если убрать обработчик OnSetText, то исключение не происходит, а запись в гриде просто возвращается в исходный вид с потерей редактирования.

Посмотрела историю ошибок на сервере. Происходит какой-то глюк при передачи данных в колонку времени. Я передаю 19:12:00 а на сервер приходит в формате даты. Администратор сервера посмотрел, но пока не разобрался, почему так происходит. Что-то с типом time в PostgreSQL. Будем разбираться. smile.gif

P.S.
Без двоеточий пишет "191200 not valid time"
olegenty
Отправлено: 05.10.2006, 15:59


Ветеран

Группа: Модератор
Сообщений: 2412



скорее проблема в драйвере, посредством которого доступаешься. либо во взаимодействии компонентов с этим драйвером.
Admin
Отправлено: 05.10.2006, 16:29


Владимир

Группа: Администратор
Сообщений: 1190



QUOTE
Можно в двух словах объяснить, почему манипуляции с ProviderFlags необходимы были в этой таблице? Почему я не устанавливала это свойство для других таблиц и там все работало?


Встроенный help — F1 на ProviderFlags.
или http://www.megalib.com/books/7/MIDASBasics.htm
---

Проблемы со временем — по-видимому как и с полем bool — от базы.
Этот код нормально работает на том-же RxMemoryData

CODE

//---------------------------------------------------------------------------

void __fastcall TForm1::MemRuleetimeSetText(TField *Sender, const AnsiString Text)
{
try{
TTime ttTime = StrToTime(Text);
MemRuleetime->AsDateTime = ttTime;
}catch(...){
ShowMessage("Неверное врeмя !");
}
}
//---------------------------------------------------------------------------


Попробуйте вообще убрать все из EditMask этого поля и ввести
значение вручную типа: 10:00:00 , может в EditMask что-то лишнее ?
Если нет — значит скорее всего — база.
Admin
Отправлено: 05.10.2006, 16:51


Владимир

Группа: Администратор
Сообщений: 1190



Попробуйте еще в OnSetText поля Ruleetime написать:

1. ClientDataSetRuleetime->AsString = "10:05:15";
если не заработает, то такой вариант:
2. ClientDataSetRuleetime->AsString = "'10:05:15'";
Лена
Отправлено: 05.10.2006, 17:15


Мастер участка

Группа: Участник
Сообщений: 501



Все перепробовала, не выходит.
Когда выйдет, разработчик этой базы, на работу спрошу у него, может просто поменять тип поля в базе и все будет нормально.
Спасибо за помощь!


Вернуться в Работа с базами данных в C++Builder