Форум: "Базы";
Текущий архив: 2006.05.28;
Скачать: [xml.tar.bz2];
Внизавтокрименентное значение Найти похожие ветки
← →
{Alex} (2006-04-05 16:51) [0]маленький такой вопросик:
Можно как нибуть получить автокрименентное значение поля,
т.е. значение которое бдет присвоено следующей записи, перед ее добавление в таблицу.
Используется MySQL&MDAC&Delphi
← →
sniknik © (2006-04-05 16:58) [1]нельзя. все ясновидческие предузнавания данных до их появления сбиваются на нет многопользовательской сущьностью sql серверов.
← →
Johnmen © (2006-04-05 17:01) [2]Только по факту
http://delphimaster.net/view/3-1143450402/
← →
Курдль © (2006-04-05 17:07) [3]
> sniknik © (05.04.06 16:58) [1]
> нельзя. все ясновидческие предузнавания данных до их появления
> сбиваются на нет многопользовательской сущьностью sql серверов.
Счазззз!!!
Все более-менее умные СУБД умеют это делать!select SEQUENCE_NAME.NEXTVAL from DUAL
select GET_IDENTITY(TABLE_NAME) from DUMMY
select Gen_ID(GeneratorName, Increment) не_помню_синтаксис_IB
← →
sniknik © (2006-04-05 17:27) [4]> Все более-менее умные СУБД умеют это делать!
а глупые программисты этим пользуются...
вообщето приведенные примеры это способ узнать текущеее значение счетчика, а не значение которое будет записано... разница однако.
надо обьяснять почему опасен код типа (а приведенные варианты это его аналог)
select max(id)+1 as NextId from table1
insert into table1 (Field1) values ("xxxx")
действия ....
update table1 set Field2 = "xxxx2" where id = NextId
т.е. с "закладкой" на расчетные/"предугаданные" данные, в многопользовательской системе?
(пример на одну таблицу, для простоты, но обычно пытаются связки в нескольких по этому значению сделать... потом приходять и сдесь глупый вопрос "почему не работает?" задают).
← →
Курдль © (2006-04-05 17:36) [5]
> sniknik © (05.04.06 17:27) [4]
> > Все более-менее умные СУБД умеют это делать!
> а глупые программисты этим пользуются...
> вообщето приведенные примеры это способ узнать текущеее
> значение счетчика, а не значение которое будет записано.
> .. разница однако.
sniknik! Ну Вы зажгли!!! Сами-то поняли, что написали?!! Поставили себя в неловкое положение, назвав тысячи программистов оракла, сайбэйса и интербэйса глупыми?
Как, по-Вашему, переводится слово после точки и до VAL в этой фразе: select SEQUENCE_NAME.NEXTVAL from DUAL?
Наверное, Вам непосчастливилось учиться работать с БД наоснове MS SQL Server, где и вправду, узнать значение нового идентификатора нельзя до тех пор, пока не вставишь строку. :)
То, что Вы пишете дальше - это уже диагноз! :) Учите албанский!
← →
sniknik © (2006-04-05 17:52) [6]> sniknik! Ну Вы зажгли!!! Сами-то поняли, что написали?!! Поставили себя в неловкое положение, назвав тысячи
> программистов оракла, сайбэйса и интербэйса глупыми?
только тех кто так пишет, закладываеться на фиктивное значение. и мне не неловко, мне комфортно. "правду говорить легко и приятно" (@ не помню чей)
> узнать значение нового идентификатора нельзя до тех пор, пока не вставишь строку. :)
можно
select IDENT_CURRENT("table_name")
> То, что Вы пишете дальше - это уже диагноз! :) Учите албанский!
ну вас тогда надо послать к основам BD
← →
sniknik © (2006-04-05 17:55) [7]> можно
> select IDENT_CURRENT("table_name")
хотя нет, предположительно следующее будет
select IDENT_CURRENT("table_name") + IDENT_SEED("table_name")
← →
Johnmen © (2006-04-05 17:56) [8]
> Курдль ©
Нет, дорогой, ты В КОРНЕ неправ.
То, что ты привёл, как примеры [3] есть простое наращивание значения последовательности или генератора. И не более того.
Причём, как ты сам понимаешь, полученное значение вовсе не означает того, что оно "будет присвоено следующей записи, перед ее добавление в таблицу".
← →
Курдль © (2006-04-05 17:59) [9]
> можно select IDENT_CURRENT("table_name")
Ну и пользуйтесь им на здоровье, если уверены, что это из того же списка, что и приведенные мной примеры!
Уверяю Вас, что никто из "многопользователей" ни при каких обстоятельствах не получит того же значение последовательности от оракла, идентификатора от сайбэйса или генератора от интербэйса. Их совершенно бесстрашно можно использовать для вставки в новую запись именно целевым значением, как Вы написалиinsert into table1 (Field1) values ("xxxx")
в случае, если одним пакетом заполняются несколько связанных по внешним ключам таблиц с первичным ключом из Вашей table1. Этот метод не только удобен, но еще и рекомендован во многих источниках. И он не имеет ничего общего сselect max(id)+1 as NextId from table1
.
← →
Курдль © (2006-04-05 18:00) [10]
> Johnmen © (05.04.06 17:56) [8]
>
>
> > Курдль ©
>
>
> Нет, дорогой, ты В КОРНЕ неправ.
> То, что ты привёл, как примеры [3] есть простое наращивание
> значения последовательности или генератора. И не более того.
>
Читайте первоисточники - завтра вернемся к обсуждению :)
← →
Johnmen © (2006-04-05 18:03) [11]
> Курдль © (05.04.06 18:00) [10]
Понятно...
Мне обсуждать нечего. И тем более, как я теперь предполагаю, с тобой.
← →
sniknik © (2006-04-05 18:37) [12]Johnmen © (05.04.06 18:03) [11]
возможно он имеет ввиду непересекаемость значений при (возьмем пример с IB, он мне всетаки ближе оракла)
получении
- SELECT GEN_ID(ID_GENERATOR, 1) AS ID FROM RDB$DATABASE //неважно с какой таблицы, в этой минимум одна запись должна быть
и последующем использовании, даже запись в то поле которое автоинкремент (в нормальном варианте обеспечивается тригером), тригер он естественно тогда не использует...
ну а так как в этом случае ID_GENERATOR это просто предопределенная глобальная переменная, то следующий вызов другим юзером гарантированно даст новое значение (вызов ее увеличит)... т.е. можно использовать без боязни коллизий, но только за значениями в самом типа "автоинкрементном" тут поле следить самому, записывать это значение...
Курдль ©
если это так. то ... мне тоже нечего с тобой обсуждать ;(.
и кстати такую схему также легко можно и в MSSQL сделать, только зачем? чесать левое ухо правой задней ногой... (ее отрастить сначала надо ;о))
← →
Джо © (2006-04-05 19:23) [13]В Postgres также есть подобные функции, currval & nextval для генераторов. Это так, до кучи.
← →
Anatoly Podgoretsky © (2006-04-05 19:51) [14]Курдль © (05.04.06 17:07) [3]
А MySql к таким относится?
Кроме того вопрос про автоинкриментные поля, а не генераторы или подобное. Я не в курсе насчет Оракла, но в ИБ это генератор, который косвенно относится к автоинкриментным полям, которых там просто нет.
← →
{Alex} (2006-04-05 20:46) [15]упс.... не думал что тут так все развернется....
Поясню суть проблеммы:
Есть база видео файлов на серваке, пользователь просматривает базу и может скачивать или добавлять свои фильмы. Все работает отлично.
Но маленькая проблема если пользователь добавляет файл, название которого совпадает с любым названием файла на сервере, то файл на сервере просто переписывается.
Добавление сведение о фильме в базу происходит только после успешной закачки.
Вот тут и приходит на ум, что бы программа автоматически переименновала файл, и называла его по индефикатору записи в базе.
← →
Anatoly Podgoretsky © (2006-04-05 22:13) [16]Тогда нет нужды в автоинкрименте, достаточно будет GUID или имя фильма + датавремя
← →
sniknik © (2006-04-05 23:11) [17]> Поясню суть проблеммы:
будем откровенны, ничего ты не поясняеш, т.к. до этого ничего сказано не было, по "проблеме", ты ее счас только излагаеш.
> Но маленькая проблема если пользователь добавляет файл, название которого совпадает ...
надуманная проблема, и решение не лучшее
не претендую, что мое будет идеалом, но делал бы по другому. использовал бы как основной уникальный идентификатор(и имя файла на сервере по совместительству) его хеш.
у тебя файловый сервер, а в базе справочник имен, и ссылка на путь/имя файла хранится? сделал бы поля (основные) - оригинальное имя файла (пользовательское, неуникальное), время закачки, хеш файла (одновременно и его имя в файловой системе)
вот хеш бы был уникальным полем (ну он по сути такой ;), поле можно обьявить ключем), рассчитавался бы по содержимому файла ("e-мул" так делает) и добавлялся бы файл только в том случае если расчитанного хеша в базе не оказалось.
преимущества, оригинальное данное юзером имя есть можно поиски делать, время закачки, чтобы по нему с одинаковыми именами различать , а дублей файлов (реальных дублей, не просто "однофамильцев", а по содержимому) нет, и не важно как юзер файл обозвал... и еще до закачки будет ясно и юзеру сказано, что аналогичный файл на сервере есть (трафик экономим).
недостаток... ну это потребует больше усилий в разработке удобной системы "заливки"/"скачки" на сервер с сервера, потому как оригинальные имена будут только в базе (клиент нужен. а в общем и с именами можно чтонибудь придумать ну например добавкой к основному делать). и будет хоть и небольшая но задержка на расчет хеша перед заливкой (компенсируются сотни таких задержек единственным отказом в повторной закачке существующего файла).
← →
Курдль © (2006-04-06 10:32) [18]Прошу извинения у автора топика за вмешательство, непосредственно не относящееся к его вопросу. Однако оно было вызвано только стремлением восстановить истину. Я не мог пропустить без ответа пост sniknik © (05.04.06 16:58) [1], который противоречит действительности.
Кроме того, придется опровергнуть еще несколько неверных высказываний.
> То, что ты привёл, как примеры [3] есть простое наращивание
> значения последовательности или генератора. И не более того.
Более того! Словоselect
означает то, что эти данные будут выбраны в набор данных, т.е. получены по запросу клиентом СУБД и могут быть использованы по его усмотрению.
> Причём, как ты сам понимаешь, полученное значение вовсе
> не означает того, что оно "будет присвоено следующей записи,
> перед ее добавлением в таблицу".
А куда оно денется, если его явно присвоить идентификатору "следующей записи"?
> sniknik © (05.04.06 18:37) [12]
> - SELECT GEN_ID(ID_GENERATOR, 1) AS ID FROM RDB$DATABASE
> //неважно с какой таблицы, в этой минимум одна запись должна быть
Нет! Не должна быть!
> запись в то поле которое автоинкремент (в нормальном варианте обеспечивается тригером),
Не "в нормальном варианте" а в частном случае. Не все СУБД используют автоинкрементные поля. И не триггером, а системным триггером.
Кстати, термин "автоинкрементное" не используется в ER-моделировании.
> и кстати такую схему также легко можно и в MSSQL сделать,
> только зачем? чесать левое ухо правой задней ногой...
Если подобная возможность и появилась в MSSQL, то лишь в последних версиях. Раньше было возможно только использование@@Identity
. Кстати, Вы задумывались, почему добавили возможность получения следующего идентификатора? Может это кому-то понадобилось больше, чем чесание левого уха правой ногой? :)
Отвечу на вопрос "зачем". Если на клиенте требуется создать структурную единицу данных, состоящую из нескольких связанных записей.
Пример: паспорт >-+ физ. лицо +-< номер телефона.
Так вот, если заранее знать "следующий" ID физ. лица, то можно спокойно создать записи в связанных таблицах, заполнив поля внешних ключей этим ID на клиенте и "отправить" их в нужной последовательности на сервер. Это хорошая альтернатива ХП.
Такой же механизм используется а ADO.NET, когда связанные таблицы многотабличного датасэта получают на клиенте псевдозначения PK и FK типа "-1", а потом эти псевдозначения подменяются реальными ID, полученными от генераторов, последовательностей и т.п.
← →
sniknik © (2006-04-06 11:08) [19]ну все понятно. отстаивается позиция описаная (предугаданная ;) в [12].
с вариантом, не автоинкримента, но с переменной. но тогда и спорить глупо т.к. значение такой переменной является сушествующим а не предуганным о чем пост [1] (против которого такое "горячее" возражение)
кстати у меня стойкое впечатления о "непонимаемости" "возражателем" аргументов...
для примера (не буду опровергать все ;о)
> > sniknik © (05.04.06 18:37) [12]
> > - SELECT GEN_ID(ID_GENERATOR, 1) AS ID FROM RDB$DATABASE
> > //неважно с какой таблицы, в этой минимум одна запись
> должна быть
>
> Нет! Не должна быть!
чего не должно быть? ты понял вообще что там и зачем? прежде чем возражать. ясно с IB знаком еще более поверхностно чем я.
дело в том что написать аналогично как в MSSQL
SELECT GEN_ID(ID_GENERATOR, 1) AS ID
там нельзя, выборка даже из функций/переменных/чего там еще должна производится в контексте выборки из таблици (может есть и другой вариант, но я не в курсе) и поэтому необходимо подставить FROM any_table, и any_table долна быть не пустой иначе пустой рекордсет вернет, хотябы одна запись должна быть а в той что я подставил одна обязательно есть... о чем и коментарий
> Если подобная возможность и появилась в MSSQL, то лишь в последних версиях. Раньше было возможно
> только использование @@Identity.
это было, и есть, рекомендованным способом и тогда и сейчас. а "подобная возможность", есть и была раньше (не скажу за 6,5 но в 7.0 это практически наверняка было (читал обсуждение по этому поводу на sql.ru))
← →
Курдль © (2006-04-06 11:21) [20]
> ясно с IB знаком еще более поверхностно чем я.
Наверное, менее поверхностно. Имею в своем портфолио самолично сделанные, внедренные и до сих пор работающие проекты с использованием IB (правда очень давние). Не поленился отрыть исходникиsSQLGetIdentity = "select GEN_ID(%s, 1) from rdb$database";
Все работает при нулевом количестве записей.
← →
Johnmen © (2006-04-06 11:35) [21]
> > То, что ты привёл, как примеры [3] есть простое наращивание
>
> > значения последовательности или генератора. И не более
> того.
>
> Более того! Слово select означает то, что эти данные будут
> выбраны в набор данных, т.е. получены по запросу клиентом
> СУБД и могут быть использованы по его усмотрению.
Прошу в дальнейшем цитировать меня полностью, и на основании этого приводить свои высказывания.
А не выдирать из контекста.
← →
sniknik © (2006-04-06 11:37) [22]> Все работает при нулевом количестве записей.
работает это компилится и выполняется? или получает значение счетчика при 0 записей в таблице вместо null (как оно обычно бывает. проверялось на ADO - OLEDB драйвер ZStyle - файребирд ембедед 1.5)
← →
Курдль © (2006-04-06 11:50) [23]
> sniknik © (06.04.06 11:37) [22]
> работает это компилится и выполняется? или получает значение счетчика при 0 записей в таблице вместо null
Работает, это получает правильное значение генератора при вновь созданной БД (0 записей во всех таблицах). (Yaffil + Delphi c компонентами TIB...).
Не пойму, о какой таблице Вы говорите? Как генератор - отдельный и самостоятельный объект базы данных, живущий отдельной жизнью, связан с какой бы то ни было таблицей?
← →
sniknik © (2006-04-06 12:30) [24]> Не пойму, о какой таблице Вы говорите?
sSQLGetIdentity = "select GEN_ID(%s, 1) from rdb$database";
таблица, системная. в ней 1 запись всегда, минимум. вот поэтому ее я и использовал если бы там была пустая таблица (с 0 записей) то возвращаемое значение было бы null независимо от значения счетчика/переменной.
а говориш знаеш IB больше меня... если учесть, что сам ститаю, что практически его не знаю... ;о))
← →
sniknik © (2006-04-06 12:37) [25]на ее месте мог быть любой (© брильянтовая рука)
а если спользовать с неденичным наполнением, наприммер
SELECT GEN_ID(ID_GENERATOR, 1) AS ID FROM RDB$FIELDS
то результат будет очень интересным ;о) (а после вопрос в форуме "почему у меня пропуски в "автоинкрементном" поле???" ;о))
прочем такой вопрос может быть и в предыдущем варианте как только количество файлов базы перевалит 1 штуку.
← →
Sergey13 © (2006-04-06 13:13) [26]2[25] sniknik © (06.04.06 12:37)
>а если спользовать с неденичным наполнением, наприммер
SELECT GEN_ID(ID_GENERATOR, 1) AS ID FROM RDB$FIELDS
то результат будет очень интересным
А зачем делать ТАК?
← →
sniknik © (2006-04-06 13:16) [27]> А зачем делать ТАК?
вот это мы как раз и выясняем ;о), и если почитаеш ветку, то поймеш что я как раз противник ЭТОГО.
← →
Sergey13 © (2006-04-06 13:24) [28]2[27] sniknik © (06.04.06 13:16)
>вот это мы как раз и выясняем ;о), и если почитаеш ветку, то поймеш что я как раз противник ЭТОГО.
Прочитал и не понял. 8-)
Есть стандартный метод получения (гарантированного) следующего значения последовательности/генератора. Если его использовать НЕ стандартно, то естественно получишь НЕ стандартный результат. Но в чем тут несовершенство стандартного метода - я не понял.
← →
sniknik © (2006-04-06 13:45) [29]> Есть стандартный метод получения (гарантированного) следующего значения последовательности/генератора.
покажи его
если использование RDB$DATABASE стандартно, то я про это не знал
просто после
> select Gen_ID(GeneratorName, Increment) не_помню_синтаксис_IB
в [12] писал пример, и зная о необходимости использования таблици пробежался по системым, выбрал подходящую с одной записью. ее и использовал.
причем судя по названию в ней хранятся инфа о файле базы какаята, а будет база состоять из двух файлов/трех .... т.д. столько записей и будет. (это мой "домысел", влезать в изучение тонкостей IB времени нет) т.е. получается, что гарантировано одной записи может не быть даже при этом (а что бывает если не одна показано на примере RDB$FIELDS)
вот, а ты теперь говориш что это стандарт в IB...? и это рекомендуют к использованию?
(если это правда то считай мое уважение к IB и подобным системам упало ниже плинтуса ;о)), только я думаю ты ошибаешся, рекомендованным этот метод быть не может. рекомендовано и стандартно там использование генератора в тригере (однозначно одноразово) для автоинкремента)
← →
Johnmen © (2006-04-06 13:52) [30]
> Sergey13 © (06.04.06 13:24) [28]
Стандартно, это NextGenValue= GEN_ID(ID_GENERATOR, 1)
что <> SELECT ... FROM xxx
>Есть стандартный метод получения (гарантированного) следующего значения последовательности/генератора.
Я бы всё же уточнил.
Есть стандартный метод получения (гарантированного) текущего значения последовательности/генератора сразу же после наращивания этого значения.
← →
Sergey13 © (2006-04-06 14:14) [31]2[29] sniknik © (06.04.06 13:45)
> причем судя по названию в ней хранятся инфа о файле базы какаята
О базе вроде (ну или о первом файле).
RDB$DATABASE defines a database. (LangRef)
О файлах вроде rdb$files.
RDB$FILES list the secondary files and shadow files for a database.
Так что не думаю что в RDB$DATABASE окажется больше 1 записи. Хотя конечно 100% гарантию дает только страховой полис. В Оракле в DUAL тоже можно еще записи вставить если есть желание базу поломать. 8-)
Про "стандартность" я говорил имея в виду "общеупотребительность". Сори за неточность.
2[30] Johnmen © (06.04.06 13:52)
> Стандартно, это NextGenValue= GEN_ID(ID_GENERATOR, 1)
что <> SELECT ... FROM xxx
Насколько я понимаю, select from rdb$database - в данном случае просто способ вернуть значение на клиента не применяя его по назначению. Иначе то вроде никак не получится.
>Я бы всё же уточнил.
Согласен.
← →
Jeer © (2006-04-06 15:08) [32]Тем не менее, в общем случае, не пользуясь autoinc или триггерами, вполне возможна организация "чистым" SQL такого псевдо-autoinc поля с возвратом ID
Обработка исключительно на клиенте:
-Select max по PK; result := fields[0].AsInteger + 1;
-Попытка вставки result до удачи заданное число раз
Так сказать, конкурентый доступ к max+1 записи.:))
Ethernet - тоже система доступа к моноканалу на основе конкуренции.
Данный метод давно опробован, тестировался и использовался неоднократно.
Основание, слегка личное - не перевариваю autoinc и есть за что.
Другое дело, что если движок поддерживает "приличные" способы разруливания таких ситуаций - этим и надо пользоваться.
← →
Курдль © (2006-04-06 15:19) [33]
> Sergey13 © (06.04.06 14:14) [31]
> Насколько я понимаю, select from rdb$database - в данном
> случае просто способ вернуть значение на клиента не применяя
> его по назначению.
Сдается мне, что заявление применить по назначению в данном контексте попахивает субъективизмом. Все зависит от принятых методов обработки данных. Меня заинтересовала эта дискуссия, поскольку появилась возможность узнать альтернативные моему, способы. Приведу конкретный пример. (Такой же я как-то приводил в похожем обсуждении).
Имеем форму ввода нового физического лица. Ничего особенного - несколько контролов ввода ФИО, пола, даты рождения и т.п. Тройка гридов для ввода телефонов, адресов (домашний/рабочий), паспортов (РФ/загран).
Как бы реализовал я. 4 датасэта + 4 датасоурса + 4 апдэйтобжекта. Пока никаких возражений? Приложение получает от сервера ID физ.лица. Юзер заполняет необходимые поля. Все новые строки всех датасэтов получают этот ID (кто в качестве PK, кто в качестве FK).
Юзер нажимает "ОК" -> DataSet.ApplyUpdates([DataSet1, DataSet2, DataSet3, DataSet4]);
Все!
Как бы Вы (вы) исполнили такую задачу?
← →
Johnmen © (2006-04-06 15:24) [34]
> Jeer © (06.04.06 15:08) [32]
Да, этот способ описан в соотв.литературе. Но, ИМХО, для продуктивной работы с полноценными SQL серверами, неприемлем.
Реализация autoinc самим сервером - гарантия надёжной работы и сведение к минимуму эффектов от ошибок разработчика приложений.
Поэтому считаю, что его надо переваривать...:)
← →
Sergey13 © (2006-04-06 16:08) [35]2[33] Курдль © (06.04.06 15:19)
> Как бы Вы (вы) исполнили такую задачу?
Я, наверное, так же как и Ты (ты). 8-)
"Не применяя его по назначению" я указал для того, что в момент взятия значение оно пока не применяется, а только резервируется. Применится ли оно потом зависит от многих факторов - например нажмет юзер "ОК" или "Отмена". Но применив это значение я практически гарантирован от коллизий.
← →
Курдль © (2006-04-06 16:08) [36]Строку DataSet.ApplyUpdates([DataSet1, DataSet2, DataSet3, DataSet4]); читать, как
DataBase.ApplyUpdates([DataSet1, DataSet2, DataSet3, DataSet4]);
← →
Курдль © (2006-04-06 16:11) [37]
> Sergey13 © (06.04.06 16:08) [35]
> Я, наверное, так же как и Ты (ты). 8-)
Ура! Счастье есть! Впервые за долгие годы со мной кто-то согласился! (шютка) :)
Но, если честно, вся эта возня забылась, как только перешел на ADO.NET - там все разруливается без руковмешательства.
← →
Jeer © (2006-04-06 16:26) [38]Johnmen © (06.04.06 15:24) [34]
> Реализация autoinc самим сервером
> Поэтому считаю, что его надо переваривать...:)
>
Спорить не буду - autoinc на сервере - почти гарантия от "наложений".
Не перевариваю по другой причине - относительная уникальность.
А точку zero - восстановить бывает сложно, если вообще возможно.
В итоге - рассогласование базы.
← →
Sergey13 © (2006-04-06 16:35) [39]2[38] Jeer © (06.04.06 16:26)
> относительная уникальность.
Это типа номера позиций в накладной или что-то другое?
← →
Курдль © (2006-04-06 16:41) [40]А мне не понятен термин "рассогласование базы."
Jeer ©! Не поясните, что за беда? Мож у меня, пока я пребывал в беспечном неведении, все базы рассогласовались и ващще распоясались без присмотра? :)
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2006.05.28;
Скачать: [xml.tar.bz2];
Память: 0.59 MB
Время: 0.011 c