Форум: "Базы";
Текущий архив: 2006.08.27;
Скачать: [xml.tar.bz2];
ВнизСчетчик (?) в Firebird Найти похожие ветки
← →
Urvin (2006-06-15 18:23) [0]Можно ли средствами сервера или запроса организовать следующую затею:
при добавлении данных в одну из таблиц (Insert Into Table1...) в одно из полей средствами сервера записывается его номер. При добавлении еще одной записи - новый номер, увеличенный на единицу.
После записи этого номера информация в ячейке не можжет изменяться, т.е. если из таблицы удаляется какая-то запись, то у последующих записей их номер не изменяется. и, например, в таблице содержатся записи #331, #332, #333. Удалим последнюю. Следующая добавленная запись будет иметь номер #334....
???
← →
Ega23 © (2006-06-15 18:33) [1]Обрати внимание на такую сущность, как генератор.
← →
Desdechado © (2006-06-15 18:33) [2]это называется генератор
в триггере перед вставкой пишешь
new.id=gen_id(genname, 1);
← →
Urvin (2006-06-15 18:43) [3]тогда вопрос - при отключении/включении сервера значение обнуляется?
должен ли я каждый раз при обращении создавать триггер и генератор?
← →
Desdechado © (2006-06-15 18:45) [4]значение хранится в базе в системных таблицах
у тебя данные очищаются в твоих таблицах, когда сервер отключаешь?
про создание - один раз
а еще почитал бы ты ibase.ru что ли...
← →
DSKalugin © (2006-06-15 18:46) [5]читай о триггерах и генераторах
http://www.realcoding.net/article/view/1578
← →
kaif © (2006-06-15 19:35) [6]Только в триггер не суй, если хочешь вставлять данные вручную. Для запроса очередного значения генератора в IBX-компонентах есть специальное свойство Generator. Правда аиногда пдейт IBX нужно поставить, чтобы его увидеть. В этом свойстве указывается, какой генератор использовать при вставке новой записи, когда его запрашивать (OnPost) и в какому полу набора присваивать.
Если сделаешь в триггере - потом будешь мучиться с поиском только что добавленной записи (при Refersh датасета).
К тому же триггеры будут мешать при всяких закачках данных.
Кстати, значение генератора после таких закачек можно установить вручную:
SET GENERATOR <генератор> TO <значение>
И даже то ли в Firebird, то ли в Yaffil работала такая конструкция:
SET GENERATOR <генератор> TO SELECT MAX(<поле>) FROM <таблица>
← →
Urvin (2006-06-15 19:57) [7]спасибо большое! разобрался!
← →
Desdechado © (2006-06-15 20:40) [8]kaif © (15.06.06 19:35) [6]
> в триггер не суй, если хочешь вставлять данные вручную
А вот это зря. Потому как в триггере всегда можно прописатьIF( new.id IS NULL ) THEN
new.id=gen_id(...);
А вот если без триггера, то ни одним скриптом нормально не вставишь данные.
> К тому же триггеры будут мешать при всяких закачках данных.
Проблемные триггеры при закачках можно отключать. Закачки ведь обычно явление редкое и не многопользовательское.
← →
unknown © (2006-06-15 21:50) [9]
> kaif © (15.06.06 19:35) [6]
> Только в триггер не суй
...
> К тому же триггеры будут мешать при всяких закачках данных.
Какой бред...
← →
Petr V. Abramov © (2006-06-15 23:36) [10]идея с генераторм плоха, если "дырки" в номерах допустимы ТОЛЬКО при удалении.
При откате транзакции (а это может случиться по сотне причин) значение генератора не откатывается.
← →
Johnmen © (2006-06-15 23:42) [11]
> идея с генераторм...
А это не идея. Это стандартный механизм.
И если кто-то волнуется по поводу дырок, то он жуёт овощ не в том месте и не в то время...
← →
DrPass © (2006-06-15 23:52) [12]Кроме того, значение генератора не есть абсолют, и в случае особо извращенной постановки задачи может быть изменено на то, что потребуется
← →
Petr V. Abramov © (2006-06-16 11:10) [13]> Johnmen © (15.06.06 23:42) [11]
> А это не идея. Это стандартный механизм.
Для генерации уникальных значений, и ни для чего другого. Можно, конечно, и не по назначению использовать, но кому-то и кобыла невеста
← →
MsGuns © (2006-06-16 13:06) [14]>kaif © (15.06.06 19:35) [6]
>Только в триггер не суй, если хочешь вставлять данные вручную.
?
Почитай Вострикова с Ковязиным хотя бы
>Для запроса очередного значения генератора в IBX-компонентах есть специальное свойство Generator. Правда аиногда пдейт IBX нужно поставить, чтобы его увидеть. В этом свойстве указывается, какой генератор использовать при вставке новой записи, когда его запрашивать (OnPost) и в какому полу набора присваивать.
Ашот, не надо всем ложащимся в постель советовать надевать презерватив. Или хотя бы пиши, что это надо при правках через датасеты, а не явными запросами. Кроме того, неплохо бы еще учитывать особенности механизма транзакций, версионность и т.д.
>Если сделаешь в триггере - потом будешь мучиться с поиском только что добавленной записи (при Refersh датасета).
Вообще не понял. Что значит "мучиться с поиском", если получить новаое значение генератора перед вставкой вообще не представляет никакой проблемы. Хоть серез датасет, а хоть через отдельный запрос. И при чем тут Refresh ? Этот метод вовсе не заставляет датасет перечитать с сервера актуальные данные. Да и вообще я бы предостерег писателей "клиенских" приложений от использования этой чисто локальной фичи
>К тому же триггеры будут мешать при всяких закачках данных.
???
В [8] все написано. Хотя, конечно, если отказаться от использования генераторов в триггерах.. Типа нафига удочка, если я могу трусами рыбу ловить.
>Кстати, значение генератора после таких закачек можно установить вручную:
SET GENERATOR <генератор> TO <значение>
И даже то ли в Firebird, то ли в Yaffil работала такая конструкция:
SET GENERATOR <генератор> TO SELECT MAX(<поле>) FROM <таблица>
А это еще что за чудо-юдо рыба-кит ? Если, конечно, с БД работает строго один товарисч, то оно канешна..
Резюме, Ашот, ты ли это ?
← →
kaif © (2006-06-16 15:32) [15]2 MsGuns ©
2 Desdechado © (15.06.06 20:40) [8]
А вот если без триггера, то ни одним скриптом нормально не вставишь данные.
Возроажаю.
При вставках явными запросами всегда можно написать (что я и делаю в таких ситуациях):
INSERT INTO AAA (ID, NAME) VALUES(GEN_ID(AAA_GEN,1), "Вася");
Или вы никогда не использовали функцию GEN_ID() в текстах SQL-запросос INSERT?
Тогда открою вам тайну.
Такая контсрукция тоже работает:
INSERT INTO AAA(ID, NAME)
SELECT GEN_ID(AAA_GEN, 1), BBB.NAME FROM BBB
Хотя возможно у Ковязина об этом ничего не сказано - не знаю. Я осваивал IB по Language Reference и американским авторам, а не по Ковязину.
Что значит "мучиться с поиском", если получить новое значение генератора перед вставкой вообще не представляет никакой проблемы.
Так вот если пользователь отказался от вставки (DataSet.Cancel), то генератор будет при таком подходе в любом случае щелкать. Я понимаю, что он резиновый. Но я нахожу это излишним действием, без которого вполне можно обойтись и делать запрос генератора на клиент непосредственно перед Post. ЧТО, СОБСТВЕННО, И ПОЗВОЛЯЮТ СДЕЛАТЬ IBX.
Странно, что все так ополчились.
Я отвечаю человеку, который еще не работал с генераторами.
Мне известно про отключение триггеров. И про отключение индексов и много еще про что известно.
Иногда я использую в триггерах контрукцию IF (NEW.ID IS NULL), так что о ней я тоже осведомлен.
У меня нет цели блистать знаниями в данном случае.
У меня была цель помочь человеку разобраться.
Так как действительно свойства Generator у IBDataSet той версии, что по умолчанию ставится в Delphi - нет.
И потому я нахожу, что сообщил ценную для автора вопроса информацию.
Кратчайший путь.
При закачках проблемы будут, если не отключить триггеры. А именно - ни чем не оправданное падение скорости вставки.
Хотя я готов взять аргумент о закачках обратно.
Дело здесь не в закачках, а ДУРНОЙ ТРАДИЦИИ, которую зачем-то создают такие, как Ковязин и многие другие уважаемые авторы.
В заключение скажу, что в триггерах я сам реализую обращения к генераторам крайне редко. Возможно большинство приложений, которые я пишу, в этом просто не нуждаются, хотя повсеместно и используют суррогатные ключи. А может быть все проще. Зачастую мне бывает нужно сообщение об ошибке, если я не указал поле ID при вставке. И я вовсе не желаю создавать себе косметический геморрой, вуалируя такие ошибки. Я человек крайне невнимательный. И если мне нужно было явно указать ID в инсерте, а я забыл это сделать в тексте запроса, то лучше я получу ошибку, чем "гладкий результат" типа "все в порядке". Но это уже моя личная манера программирования, которую я никому не навязываю. Если кто-то хочет избавитьсяот всех возможных ошибок априори - его право. Может даже перехватить Application.OnException и вписать туда exit.
И вообще я вам скажу, что ничто так не сбивает с толку начинающего осваивать генераторы, как использование генератора в триггере. И именно из-за Refersh.
Насчет Refresh скажу яснее. Если вы в IBDataSet вставите новую запись, которая получает значение ID из генератора в триггере, то запрос Refresh (который, кстати, IBDataSet выполняет автоматически после Post), не сможет найти вновь вставленную запись, если у вас отсутствует какой-нибудь альтернативный ключ.
То есть грамотное решение для IBDataSet, который юзает таблицу с генератором в триггере должно выглядеть примерно так:SelectSQL.Text := "select id, name from aaa";
ModifySQL.Text := "update aaa set name = :name where id = :id";
DeleteSQL.Text := "delete dfom aaa where id = :id"l;
RefresSQL.Text := "select id, name from aaa where name = :name";
И при этом необходимо иметь UNIQUE (NAME) !!!!
Или какое-нибудь иное уникальное поле, например, UNIQUE(CODE).
Иначе Refresh просто не заработает.
А если Refresh не заработает, то после Post датасет не сможет извлечь новое значение ID. А это чревато, например, тем, что если на клиенте имеется два датасета (Master и Detail), связанные через свойство DataSource, то при попытке вставить и послать запись из Detail датасета у того будет NULL в поле ссылки на главный датасет и возникнет ошибка внешнего ключа при верно организованной базе данных.
И вместо того чтобы нападать на меня лично и советовать читать Ковязина пусть лучше мне покажут, как именно КЛИЕНТ узнает значение, только что присвоенное полю ID при INSERT, если таблица (а таких таблиц бывает очень много) устроена так:
ID, NAME
и в ней ID присваивается в триггере.
Уникальный ключ на NAME не предлагать!
Ответьте. И тогда я признаю, что kaif - дурак.
← →
kaif © (2006-06-16 15:41) [16]SET GENERATOR <генератор> TO SELECT MAX(<поле>) FROM <таблица>
А это еще что за чудо-юдо рыба-кит ? Если, конечно, с БД работает строго один товарисч, то оно канешна..
Да. Это именно когда работает один товарищ.
Который сделал Database Shutdown, закачал данные из какой-то другой базы, из которой ID брался явно, так как он перекачивал связанные талицы и не хотел геморроиться.
А затем установил значения генераторов туда, куда нужно.
И потом открыл общий доступ к базе.
Я не думал, что все надо разжевывать.
Просто сообщил информацию, что эта конструкция в одном из серверов работает (Yaffil иолиFirebird). В другом, кстати, на работает. А в каком именно работает - не помню, так как склероз. :)
Но попробовать ее рекомендую.
Может пригодится когда-нибудь при ручной работе.
← →
Desdechado © (2006-06-16 16:12) [17]kaif © (16.06.06 15:32) [15]
Зачем столько обиды-то?
Просто показали, что твой подход должен быть аргументирован (что ты и попытался сделать).
> Уникальный ключ на NAME не предлагать!
Я еще не встречал таблиц, в которых нет какой-либо уникальности и при этом которые заполняются вручную в сетке. Без уникальностей - это какие-то тупые протоколы/показания датчиков и т.п.
Остальные все равно имеют нечто (часто из нескольких полей) уникальное, по которым можно выудить и полученное от генератора значение поля.
Почему я использую подход с триггером - просто я не использую заточенные под IB компоненты. А в универсальных удобнее делать, как у людей, особенно в случае использования нескольких СУБД одновременно.
Скажу по секрету, Вострикова с Ковязиным не читал. Читал доки на инглише.
← →
Desdechado © (2006-06-16 16:19) [18]кстати, мастер-деталь тоже использую крайне редко, в основном для показа данных, а не редактирования
> INSERT INTO AAA (ID, NAME) VALUES(GEN_ID(AAA_GEN,1), "Вася");
Можно так, конечно. Но вижу сразу проблему. Например, у тебя есть скрипт из какой-то БД для массовой закачки. Ты будешь его модифицировать для использования генератора? Зачем? А триггер можно ли включить или нет, не трогая скрипт, а только зная, что он из себя представляет.
Да и для случаев ручного ввода данных минуя твою программу без генератора с триггером тяжко.
Все указанное не отметает твоих аргументов и подходов.
Но я не нахожу их настолько очевидными и хорошими, чтобы советовать новичкам. Тем паче, если они не знают тонкостей. Пусть лучше сами дойдут до каких-то решений, но только ПОСЛЕ того, как попробуют традиционный подход. Если захотят, конечно.
← →
MsGuns © (2006-06-16 16:51) [19]>kaif
Полностью согласен с Сашей (посты [17],[18]), в том числе и по поводу твоей, Ашот, обиды.
По поводу Ковязина. Я сам неоднократно критиковал его книги из-за явного и наглого :) лоббирования фибпласа. Однако про генераторы, триггера, транзакции и прочее у него написано очень неплохо.
То, что у тебя работает, есть частный случай, но не правило - и в этом вся причина наших возражений.
Я, к примеру, вообще стараюсь избегать "услуг" TIBDataSet в части редактирования, да еще и в связке Master-Detail. Хотя бы потому, что это усложняет мне явное управление транзакцией. И я не одинок.
Если уж приспичит юзеру править "как в экселе" (хотя это и дурная мода, т.к. дает иллюзию монопольного владения таблицей, что в принципе неверно), то я ему обеспечу и редактирование в гриде, и всякие чеки, выделения-перемещения, копирования и пр. другими способами, коих в дельфи можно нарыть без ограничений. Но привязывать технологию обмена данными с сервером к пользовательскому интерфейсу считаю в корне неверным подходом при разработке клиентских приложений.
Что же касается "заливок", о которых ты упоминал, то они делаются вовсе не датасетами, не генераторами и триггерами, а совсем иначе. О чем, кстати, тоже неплохо писано у Ковязина.
А наиболее верный подход - максимум выноса всей "правки" БД на сервер - в ХП, триггера и процедуры. Т.е. читаем датасетом, правим с помощью соотв.серверных средств. Потом перечитываем. Во всяком случае эта технология избавляет от гемора редактирования кода многочисленных "клиентов" при малейших изменениях в БД. Да и регулирует те же права на доступ к объектам БД.
Ты человек опытный и знающий, в этом нет сомнений. И должен знать, что то, что можно сделать по необходимости и "в тему" (как у тебя) еще не значит, что это может быть правилом. По крайней мере я бы поостерегся советовать подобные "художества" новичкам, слабо понимающим не только работу интербэйза, а вообще клиент-серверную "идеологию"
Извини, если что..
← →
kaif © (2006-06-16 17:04) [20]2 Desdechado ©
Ладно, извини, погорячился.
Спасибо за спокойный ответ и за то, что удалось избежать перепалки. Я уже так привык к жестким перепалкам в "Прочем", что на все реагирую неправильно.
Я понял твой подход.
В принципе со многим согласен, кроме, пожалуй, того, что я чаще как раз склонен затачивать приложение под СУБД. ...Но это целый философский спор, причем, вечный (затачивать/не затачивать под СУБД) :)
Просто мне кажется, что новичка всегда вдохновляет то, что может сразу начать работать - с одной стороны, и прояснить механизм для понимания - с другой. Собственно, люди на форум и ходят для того, чтобы получить направление для быстрого понимания и решения своей проблемы. А фундаментальные сведения всегда можно почерпнуть из документации, книг или просто ища в поисковике статьи на какую-то тему.
Так как IBX-ы как бы всегда под рукой, я всегда советую новичку начать именно с их освоения. Они вовсе не так плохи - минимально наворочены, не используют БДЕ, хорошо совместимы по версиям.
Их исходный код позволяет многое понять и, что важно - он всегда под рукой...
В любом случае получившийся спор тоже может оказаться полезен автору вопроса.
← →
kaif © (2006-06-16 17:25) [21]2 MsGuns © (16.06.06 16:51) [19]
А разве я где-нибудь настаивал на каком-то правиле?
Наоборот, я как раз пытался устранить навязываемое правило: "обязательно обращаться к генератору в триггере BEFORE INSERT". Я нахожу это правило вредным. И не вижу иного происхождения для него, кроме как попытки универсализировать приложение под разные СУБД, имитируя поле типа "автоинкремент", которое IB не поддерживает.
Что касается Master-Detail в гридах, то я тоже так не делаю. Что не избавляет от необходимости все равно иметь ID, если нужно вводить Detail данные.
Возьму простой пример.
Создаем документ типа накладная. Имеется шапка и позиции. Я нахожу нормальным позиции вводить в гриде. Скажешь нет? Так вот после создания шапки (неважно как, пусть даже в отдельном модальном окне) потребуется, как ни крути, знать ID документа.
Сейчас мне скажут - запроси ID по уникальности дата+номер.
OK.
Но зачем?
Только потому что это "классика"?
А ничего, что я так и делал (запросы по альтернативным ключам) несколько лет подряд, пока тщетно пытался писать хорошие программы, нечувсвтительные к типу СУБД, пока не понял, что хорошую программу я так не напишу никогда. Так как это просто, видимо, не мой стиль. А как только я стал заниматься исключительно приложениями под заранее известную СУБД, вот тут я и обнаружил, что "классика" вовсе не так хороша, как кажется, и доставляет больше неудобств, нежели преимуществ.
Например, я сделал альтернативный ключ дата+номер+контрагент. Но затем оказалось, что этого мало. Нужно переделать базу так, чтобы уникальность была жестче. Например, дата+номер+отдел.
Теперь докажите мне, что переделок в приложении будет меньше, чем в моем случае, когда я опирался только на ID при Refresh.
В общем. Дело не в переделках, а в разных манерах.
Еще раз повторюсь - я не навязывал правило.
Я лишь пытался не дать навязать правило, которое сам отверг и ни секунду об этом не жалею.
← →
kaif © (2006-06-16 17:40) [22]Я не считаю догмой даже такие священные понятия, как "бизнес-логика на сервере". Например, те же проверки диапазонов вводимых значений. Я практически никогда ими не пользуюсь. Скажете неправильно? А я вам скажу - я еще ни разу не слышал жалоб от юзеров на то, что компьютер не отловил ошибку диапазона. Возможно просто у меня юзеры никогда не вводят всякую ерунду без особых на то причин. И те случаи, когда особо оговаривалось, что нужны такие проверки, я их реализовывал не на сервере, а на клиенте. Так как эти диапазоны бывали весьма условны и юзерам нужно бывало их настраивать самостоятельно.
Единственные священные коровы, которые для меня остались от всей бизнес-логики на сервере, это: суррогатные ключи, правильные уникальности, NOT NULL и декларативная ссылочная целостность.
То есть все, что касается НОРМАЛИЗАЦИИ.
Все. Остальное все - не так важно.
ИМХО, конечно.
Что касается совращения новичков...
Кто и где запросит генератор... Какая на фиг разница?
О генераторах IB важно лишь знать один единственный существенный факт - генераторы IB работают вне контекста транзакций.
Все.
Все остальное в использовании генераторов - дело вкуса.
← →
TohaNik © (2006-06-16 18:12) [23]
> kaif © (16.06.06 17:40) [22]
</I
> Я не считаю догмой даже такие священные понятия, как "бизнес-
> логика на сервере". Например, те же проверки диапазонов
> вводимых значений. Я практически никогда ими не пользуюсь.
> Скажете неправильно? А я вам скажу - я еще ни разу не слышал
> жалоб от юзеров на то, что компьютер не отловил ошибку диапазона.
> Возможно просто у меня юзеры никогда не вводят всякую ерунду
> без особых на то причин. И те случаи, когда особо оговаривалось,
> что нужны такие проверки, я их реализовывал не на сервере,
> а на клиенте. Так как эти диапазоны бывали весьма условны
> и юзерам нужно бывало их настраивать самостоятельно.
>
Ну чего ты разнервничался:)
Диапазоны в справочник констант, настраивай из приложения, проверяй на сервере.
Да у всех извилины по разному устроены, твой подход к неоторым вопросам оказался для многих нестандартным, а может и непонятным.
Ну MsGuns как всегда очень быстр на похвалы:)
← →
kaif © (2006-06-16 21:35) [24]2 TohaNik ©
Хорошо.
Если по-твоему я неспособен догадаться до таких вещей, как хранить настройки диапазонов в таблицах, которые может редактировать юзер, а проверять диапазоны в триггерах, то ты ошибся.
Так как не так давно я советовал здесь в Базах Данных одному товарищу именно так и поступить.
Здесь речь шла о диапазонах, проверяемых при помощи CHECK VALUES, то есть системными триггерами. И для редактирования этих настроек надо дать юзеру возможность изменять метаданные.
Если же ты не понял, то у нас с тобой действительно извилины по-разному устроены.
В общем. Думайте обо мне что хотите. Мне как-то совершенно по барабану. Я уже давно заметил. что основным мотивом участника этого форума вместо мысли "а почему бы не обсудить и такой вариант?" должна стать мысль "что обо мне будут думать?" и "как бы мне не уронить здесь свой жалкий авторитет?".
:(
Я не претендую здесь на звание мастера, так что все ревнители правильных подходов могут спать спокойно.
Я просто играю в игру "я всего лишь пытался вам помочь". Есть такая игра для невротиков.
Иногда мне бывают благодарны участники.
И этот результат для меня больше значит, чем какие угодно мнения мэтров.
Так как я сам частенько получал здесь неоценимую помощь.
И уверяю вас, у меня никогда не было проблем, связанных с тем, что меня, как новичка направили "куда-то не туда". Потому что я всегда полагал, что когда я использую чей-то совет, то прежде всего важно чтобы у меня были мозги, а не у советующего. Так как советующий советует, а пишущий пишет. И здесь - терпение пророков.
Я не боюсь пойти по ложному пути.
И поэтому не боюсь направить кого-то другого по ложному пути.
Так как у каждого - свой путь.
← →
Андрей Пазик (2006-06-18 22:57) [25]юзай insert returning, в триггере дергай генератор.
Начиная с FB 2.0
← →
DrPass © (2006-06-19 02:13) [26]
> Андрей Пазик (18.06.06 22:57) [25]
Релиза FB2.0 еще не существует. А следовательно, юзать ее не нужно
← →
Desdechado © (2006-06-19 13:28) [27]> основным мотивом участника этого форума...
И снова обиды. Зря. На обиженных воду возят. Пост [22] стал бы хорошим завершением, с грамотной аргументацией. А [24], имхо, перевел все в личную плоскость, что у новичков вполне может отбить желание вообще что-то из всей этой дискуссии использовать.
> Так как у каждого - свой путь.
Вспомнилось:
"Каждый идет к истине своим путем. А на перекрестке сижу я, Будда..."
← →
kaif © (2006-06-19 18:50) [28]2 Desdechado ©
Ты прав.
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2006.08.27;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.039 c