Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];

Вниз

Проблемы со вставкой пустых значений   Найти похожие ветки 

 
Рустем   (2004-01-10 10:43) [0]

Здравствуйте !
Даже не представлял, что могут быть такие грабли...
Работаю IBX/Delphi6/FB1.5
Как при вставке новой записи в Грид получить в строку значения полей по умолчанию, определенные в базе ?
Или хотя бы как заставить приложение/сервер их туда подставить, если пользователь не ввел значение для поля, которое создано как Not Null, но для которого определено значение по умолчанию ?
Назначание для объекта поля свойства
AutoGenerateValue := arDefault;
ни к чему не приводит.

Единственное, что смог выяснить, так это то, что вставка с незаполненным обязательным полем будет возможна только в том случае, если:
1. Свойство объекта поля Required установить в False;
2. Из текста SQL-запроса, сформированного в компоненте IBUpdateSQL.InsertSQL, удалить упоминание о вставке в данное поле и удалить параметр, который задает для него значение.
Вот тогда сервер подставит для такого поля значение по умолчанию.

Но это просто жуть какая-то ! Мне что, нужно каждый раз анализировать ввод пользователя и строить запрос Insert "вручную" ?! Не может быть !
Для чего тогда вообще существует свойство InsertSQL ?!

И даже в этом случае "на повестке дня" остается вопрос о получении во все поля их значений по умолчанию при вставке пользователем новой записи.

Мне кажется, что решение где-то на поверхности, но я его не нашел :((

Будьте любезны, подскажите как правильно сделать сие !

Огромное спасибо !


 
Desdechado   (2004-01-10 11:39) [1]

1. насколько я знаю, значение, определенной в БД по умолчанию, нельзя достать ДО записи в БД (т.е. при вставке в локальный кэш на рабочей станции до commit)
2. required - это для полей not null, без разицы, есть ли для них умолчание
3. имхо, InsertSQL - это для общего случая, а если хочешь с умолчаниями, пиши ручками


 
Рустем   (2004-01-10 18:03) [2]

Благодарю за ответ.


 
kaif   (2004-01-10 18:34) [3]

Рекомендую просто добавить триггер на INSERT к таблице в базе и прописать там что-то вроде
IF (NEW.MY_FIELD IS NULL) THEN
NEW.MY_FIELD = MY_DEFAULT_VALUE;
Кстати, рекомендую такой триггер и на UPDATE тоже поставить (хотя от задачи зависит).


 
Sergey_Masloff   (2004-01-10 21:55) [4]

kaif © (10.01.04 18:34) [3]
>Рекомендую просто добавить триггер на INSERT к таблице в базе и >прописать там что-то вроде
Триггер это хорошо но... не всегда. Скажем если эти значения по умолчанию имеют значение для пользователя. Триггер хорош для простановки "непользовательских" значений типа времени создания и автора, для информативных значений я использую несколько иной подход. Генерируются хранимые процедуры которые возвращают курсор со значениями по умолчанию. При добавлении пользователем записи (пока что в кэш) процедура дергается и заполняет ему все что нужно по умолчанию - и он кагда жмет сохранить видит что он сохраняет. Все это описано в базовых классах форм так что при разработке никаких дополнительных расходов связаных с реализацией такого поведения нет.


 
Рустем   (2004-01-10 23:10) [5]

to Sergey_Masloff:

Будьте любезны, если можно текст ХП, а то у меня самого знаний не хватит воспользоваться Вашей подсказкой. :((

Спасибо !

to kaif: Вам также спасибо: я подозревал, что триггеры должны работать, только времени сегодня нет проверить.


 
Sergey_Masloff   (2004-01-10 23:47) [6]

Да текст то тривиальный но он меняется в зависимости от твоей таблицы. Ну на пальцах: вот у тебя связь мастер-деталь между человеком и его телефонами. Человек у тебя есть (пусть имеет ID=1) и есть список его телефонов. Ты добавляешь новый телефон. Нпример, в обработчике OnNewRecord делаешь запрос к базе к процедуре такого типа

create procedure newphone(ownerid integer)
returns (id integer, class integer, classname varchar(40))
as
begin
id = GEN_ID(gen_phones_id,1)l
class = 12345;
classname = "домашний";
suspend;
end


То есть получаешь значения новой записи по умолчанию. Единственно что тут требует комментария это class и classname. Наверное, в новой записи должны присутствовать какие-то аналитические признаки, например тип телефонного номера или что-то еще. Я думаю не стоит пояснять что такого рода аналитика обычно является ссылками на значения кодификатора (справочника). Допустим у признака "домашний телефон" код 12345 а у "мобильный" код 123457. По умолчанию вставляем ссылку на кодификатор и это хорошо. Но пользователю хочется не ссылки а имени. Обычно это достигается соединением (джойном) рабочей (операционной) и справочной таблицы. Тут мы берем на себя эту функцию и вместо джойна явно прописываем декодированное значение (в данном случае слово "домашний"). Впрочем если пользователь захочент в новой записи отредактировать это поле мы ему конечно покажем соединенную таблицу чтобы он нашел что нужно. Но может его устроит и значение по умолчанию? Вобщем, в этом духе.


 
Vemer   (2004-01-11 00:45) [7]

В IBX не прописываю в SQL и в UpdateSQL (в Insert и/или везде) поля, которые надо по Default заполнять, все работает как надо.


 
Vemer   (2004-01-11 00:50) [8]

В IBX не прописываю в UpdateSQL (в InsertSQL) поля, которые надо по Default заполнять, все работает как надо.


 
Vemer   (2004-01-11 00:53) [9]

Сорри за повтор, не специально. Второе сообщение более правильное, первое более "многофункциональное". Просто нажал Добавить - и тишина. Исправил, нажал снова. Итог перед вами.


 
Рустем   (2004-01-11 02:21) [10]

Спасибо всем отвечавшим !

to Vermer: да, это выход. Я практически "дошел" до такого вывода, прежде чем задавать вопрос. Но тут ведь не устраивает 2 момента:
1. Никакой автоматической связи с метаданными (поля и их дефолты можно ведь потом изменять и т.д.).
2. Нет возможности получить дефолты при начале редактирования новой записи.
Но ответ Ваш весьма ценен для меня, т.к. я увидел, что и другие люди так делают.

to Sergey_Masloff: Я понял Ваш способ. Просто по первому ответу мне показалось, что Вы каким-то образом получаете-таки значения дефолтов в процедуре. А Ваша процедура - это замена триггера (о чем тут уже шла речь), который, в свою очередь, замена дефолта.

Я очень признателен Вам за подробный ответ и думаю, что это вполне приемлемый метод, которым я и буду пользоваться при необходимости.

Если же не будет необходимости в предварительном показе дефолтов и структура таблицы кажется устоявшейся, то будем использовать метод Vemer.

Еще раз всем большое спасибо !

PS: Первое впечатление от форума оказалось обманчивое :))


 
Vemer   (2004-01-11 03:21) [11]

Поправочка - насколько я знаю - DEFAULT не изменить (IB 6.0). Если только метаданные ручками. Или есть другой способ (не триггер)?


 
Johnmen   (2004-01-11 03:32) [12]

>Рустем

1. Данные о дефолтных значениях полей к.-л. таблицы можно получить запросом к соотв.системной таблице.
2. Если использовать FIBPlus, то там вообще эта функциональность уже присутствует.


 
Рустем   (2004-01-11 03:50) [13]

Черт, вот что значит по ночам работать ! Конечно, господин Vermer, мы с Вами насчет Вашего способа не правы ! Ничего, кроме дефолта при таком способе в поле не вставить !
Да, насчет ФИБ я в курсе. Но надо IBX.
А вот насчет запросов к сист. табл. - я это себе представляю. Только вот не представляю, какой это конкретно запрос, и еще я себе не представляю, стоит ли так вообще работать с базой.
Это ведь сразу "намертво" привязаться к одному серверу и, возможно, только определенной версии...

А вариант Sergey_Masloff вполне инвариантен к выбору сервера.

Таким образом, остается этот вариант и вариант с триггерами.

Спасибо !


 
Johnmen   (2004-01-11 03:56) [14]

Видимо у нас разные понятия о DEFAULT значениях и откуда они берутся...:)


 
Vemer   (2004-01-11 10:25) [15]

Нет, почему, я Default отлично применяю в нек. случаях. Особенно в тех полях, к которым у проги доступа нет ("флаговые"). А если что - триггер пишеться и все. Вообще я знаю 3,5 способа заполнять поле по умолчанию.
1а - после Insert ручками
1б - на onNewRecord
2 - способ указания значений вместо :Field в UpdateSQL
3 - "неуказание" поля там-же, заполнение по Default или триггеру.


 
kaif   (2004-01-11 15:19) [16]

Я, например, не сталкивался с проблемой начальных значений. Как правило, необходимость бывала лишь избавляться от значений NULL. То есть присвоение 0 или "".
Если же иногда применяются значения по умолчанию, то не вижу никакой необходимости юзеру их предварительно показывать. После первого раза, когда он их увидит, скорее всего, запомнит навсегда...
Есть еще одна проблема. Если после AfterInsert вставить значения, то, например, в DBGrid уже не так просто отменить добавление записи простым возвращением курсора на прежнее место. Нужно делать явный DataSet.Cancel.

Что касается системных таблиц, то Johnmen © (11.01.04 03:32) [12] дело пишет. От версии к версии эти таблицы не меняются. По крайней мере, не менялись на моей памяти от IB4.* до Firebird1.5.
Я лично не пытался добывать оттуда дефаулты, так как не проектирую базы в которых они бы как-то менялись в дальнейшем. Вот только что попробовал сделать такой запрос:

SELECT
*
FROM
RDB$RELATION_FIELDS RF,
RDB$FIELDS F
WHERE
RF.RDB$RELATION_NAME = <имя таблицы> AND
RF.RDB$FIELD_SOURCE = F.RDB$FIELD_NAME

Там в MEMO-полях RDB$DEFAULT_SOURCE
что-то есть, но так на глаз не видно, что, а CAST AS VARCHAR что-то не работает. Моя ISQL мемо-поля не показывает.

Судя по описанию IB, там хранится то, что надо:

RDB$DEFAULT_SOURCE BLOB 80 Subtype Text; SQL description of a default value

Правда DEAFULT может быть у DOMAIN и у FIELD. Это тоже нужно иметь в виду... (RF.RDB$DEFAULT_SOURCE и F.RDB$DEFAULT_SOURCE)


 
kaif   (2004-01-11 15:31) [17]

Мне кажется идеологически правильно подходить к этой проблеме так: серверу серверово, клиенту клиентово. DEFAULT значения на сервере должны обеспечивать самую грубую функциональность (устранение значений NULL и т.п. самые базовые, на самый "худой конец", подстановки).
Основная работа со значениями по умолчанию должна производиться на клиенте. Ведь может так случиться, что юзеру нужно будет дать возможность настроить значения по умолчанию? Так что, снабжать его механизмами DML или, что более вероятно в данном случае (так как DEFAULT значения не так легко поменять командами ALTER TABLE ALTER COLUMN, если вообще это возможно...), вмешательством в системные таблицы?
Не лучше ли завести банальную таблицу
CREATE TABLE MY_DEFAULT_VALUES(
TABLE_NAME CHAR(31),
FIELD_NAME CHAR(31),
DEFAULT_SOURCE BLOB SUBTYPE TEXT,
PRIMARY KEY (TABLE_NAME, FILED_NAME))
?
И там хранить все, что душе угодно. И юзать как хочется..
Можно даже сделать так:
CREATE TABLE MY_DEFAULT_VALUES(
TABLE_NAME CHAR(31),
FIELD_NAME CHAR(31),
USER_NAME CHAR(15),
DEFAULT_SOURCE BLOB SUBTYPE TEXT,
PRIMARY KEY (TABLE_NAME, FILED_NAME, USER_NAME))

И хранить для каждого юзера свои настройки.
В общем, я бы так подошел к этой проблеме.
А напрягать DEFAULT значения полей сервера более чем на
DEFAULT 0 или DEFAULT "" я не считаю правильным подходом.


 
kaif   (2004-01-11 15:33) [18]

Пардон, механизмами D DL


 
Vemer   (2004-01-11 16:09) [19]

Только клиенту фигово обрабатывать поля, к которым он доступа не имеет (флагово-контрольные). Они не всегда есть конечно.


 
Sergey_Masloff   (2004-01-11 16:40) [20]

kaif © (11.01.04 15:19) [16]
>Я, например, не сталкивался с проблемой начальных значений. Как >правило, необходимость бывала лишь избавляться от значений >NULL. То есть присвоение 0 или "".
>Если же иногда применяются значения по умолчанию, то не вижу > никакой необходимости юзеру их предварительно показывать.
ой ли? А какой-нибудь счет с тучей аналитики? Способ оплаты - банк, касса или там взаиморасчет или еще 20 способов, валюты, субсчета - все это пользователь у вас помнит с первого (десятого, сотого) раза? Или до нажатия на кнопку подтверждения вставки ему это показывать и не нужно? А когда он с ужасом увидит что он там наподставлял?

Кстати мой вариант (конечно никакой он не мой, я его вариации видел в самых различных системах) не исключает применения таблицы с настройками - что мешает процедуре слазить за частью значений в таблицу? Более того, есть возможность настолько гибкого применения что... ;-) Описывать конечно долго ну тут додумать элементарно. В частности, варьирование значений по умолчанию не только от настроек пользователя которые он сам сделал а и от настроек которые ему настроил администратор, да много чего навернуть можно.


 
kaif   (2004-01-11 18:18) [21]

2 Sergey_Masloff (11.01.04 16:40) [20]
Мне все же кажется, что мы говорим несколько о разных вещах. Что имеется в виду под DEFAULT в определении поля с точки зрения сервера? Всего лишь значение, которое будет подставлено INSERT-ом, в котором это поле вообще не фигурировало явно. И ничего более! Это, собственно, и происходит. Но этого почему-то мало... Потребность определить в DEFAULT определений полей (доменов) разнообразные начальные (настроечные) значения типа ставки НДС и др. это безудержное желание во что бы то ни стало "перенести всю бизнес-логику на сервер", как это модно говорить. И больше ничего. Для меня очевидно, что подстановка начальных значений - дело клиента. Иногда удобно эти значения запоминать в местном реестре Windows, иногда нужно создавать глобальные таблицы для этого. Иногда вообще проще забить какие-то значения в текст программы...
Если бы DEFAULT значения полей и доменов предназначались для присвоения начальных значений в том смысле, о котором задан вопрос, то, ИМХО:
Синтаксис ALTER TABLE...ALTER COLUMN был бы более развит для модификаций типа ALTER TABLE...ALTER COLUMN ... DEFAULT ...
Кстати, для таких модификаций требуются привилегии SYSDBA или OWNER, что, согласитесь, вообще глупо, если речь идет вообще об индивилуальной настройке под юзера, например.
Насчет Вашего аргумента, что юзер должен что-то видеть, Вы правы, просто мы говорим о разных ситуациях. Я говорил о ситуации, когда юзер ничего не вводит в числовое поле и потом обнаруживает в таком поле 0. Это нормально. Я не имел в виду, что он не вводит НДС, а потом обнаруживат, что он 20%, а он хотел 18%, а потом уже "поздно что-то менять". Я говорил о самых примитивных DEFAULT-ах, которые всегда можно запомнить, а именно:

числовые поля: 0
строковые поля: ""
поля даты: "NOW"

уж столько-то любой юзер запомнит...
А это и есть те DEFAULT-ы, которые я предлагаю использовать при определении полей таблиц.
А все остальное можно реализовать по-разному.
Речь шла о том, что автор вопроса пытается сделать какие-то подстановки именно в DEFAULT определениях полей. Потом сталкивается с проблемами. Required=Flase он прошел. Далее было предложение с триггером, которое решает второй этап проблемы: когда с клиента посылается NULL явно, но не хочется, чтобы сервер ругался, если поле NOT NULL и у него есть DEFAULT. Кажется логичным, что сервер не должен был бы вообще ругаться в таких случаях, а просто это DEFAULT подставлять... Но это спорный момент.
А то, что юзер не видит какие-то DEAFULT после добавления записи в своих интерфейсах это уже просто другая задача. Я пытаюсь их разделить (эти две разные задачи). Ограничив DEFAULT определения полей самыми примитивными вещами.

Я приведу пример ситуации, когда вообще глупо начальное значение поля с сервера запрашивать. Например, я хочу запоминать в каком-то поле время. По умолчанию запоминается текущее. Для красоты, чтобы показать юзеру, что это именно так, я вообще вывожу время on-line в этой ячейке. С мигающими двоеточиями и переключающимися секундами, к примеру. Пока он руками не отредактирует это поле - это так. Это дурацкий и гипотетический пример. Но он показывает, что здесь нет общего решения на все случаи жизни.
С уважением. :)


 
Sergey_Masloff   (2004-01-11 18:53) [22]

>это безудержное желание во что бы то ни стало "перенести всю >бизнес-логику на сервер",
ну да, что-то в этом роде. Для многих задач это оптимально. Правда, для других недопустимо а для третьих хорошо в разумных пределах. Вобщем, как обычно ;-)

>Я говорил о самых примитивных DEFAULT-ах, которые всегда можно >запомнить, а именно:
>числовые поля: 0
>строковые поля: ""
>поля даты: "NOW"
ну это однозначно триггер ;-)

>Но он показывает, что здесь нет общего решения на все случаи >жизни.
точно

>С уважением. :)
взаимно


 
Рустем   (2004-01-11 19:36) [23]

to Johnmen:
>Видимо у нас разные понятия о DEFAULT значениях и откуда они берутся...:)
Да, согласен. Берутся они из старого опыта использования BDE-Paradox. Чего у опытных пользователей IBX уже нет. Надеюсь (и верю), что Вы к ним относитесь...
А я вот "по старой памяти" их пытался "пристегнуть", где и поимел проблемы.
Ситуация для меня прояснилась, если дискуссия будет продолжаться, то буду с интересом за ней следить, но еще раз хочу подчеркнуть: "У автора вопроса по большому счету вопросов больше нет".

Еще раз всем большое спасибо ! Информация была весьма ценна для меня !



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.043 c
1-16370
SniZ
2004-01-24 00:04
2004.02.06
На счёт проверки строки...


1-16366
Mihey
2004-01-23 22:08
2004.02.06
Сохранить регион в файл и загрузить.


7-16747
GleB
2003-11-22 01:23
2004.02.06
Реестр из-под DOS


7-16770
Fidgety
2003-11-22 10:15
2004.02.06
Как эмитировать клик мыхой?


1-16498
Vvedensk
2004-01-26 19:52
2004.02.06
Как лучше удалить из масива элементы?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский