Текущий архив: 2006.09.03;
Скачать: CL | DM;
Вниз
Каким образом получить только что вставленную в таблицу базы? Найти похожие ветки
← →
Lex_! © (2006-06-21 10:39) [0]Доброго времени суток.
Вопрос собственно: каким образом можно получить только что вставленную запись? Допустим в запросе, при вставлении записи генерируется id (уникальный идентификатор вида: {F3758C08-7BA6-4251-8BC3-C2A4476E17D3}) - каким образом можно сразу же получить этот идентификатор? (с момента вставки записи и до момента выполнения запроса на выборку может быть вставлено еще несколько записей... )
← →
Sergey13 © (2006-06-21 10:42) [1]Получить новый идентификатор перед вставкой.
← →
Lex_! © (2006-06-21 10:57) [2]Вообще значение заполняется автоматически ID:uniqueidentifier:(newid())
т.е. я просто вставляю запись (вообще без значений) все поля заполняются сами, но ... нужно сразу же взять ID и отправить его клиенту (это всё делается в ISAPI dll)....
Возможно я чего-то не понял ... на примере если можно покажи
← →
Ega23 © (2006-06-21 11:01) [3]
> Доброго времени суток.
> Вопрос собственно: каким образом можно получить только что
> вставленную запись? Допустим в запросе, при вставлении записи
> генерируется id (уникальный идентификатор вида: {F3758C08-
> 7BA6-4251-8BC3-C2A4476E17D3}) - каким образом можно сразу
> же получить этот идентификатор? (с момента вставки записи
> и до момента выполнения запроса на выборку может быть вставлено
> еще несколько записей... )Set NoCount ON
Declare @GUID uniqueidentifier
Select @GUID=newid()
Insert into Table (ID, .....)
Values (@GUID, .....)
Set NoCount OFF
Select GUID=@GUID
← →
Ega23 © (2006-06-21 11:02) [4]
> Вообще значение заполняется автоматически ID:uniqueidentifier:
> (newid())
Если так, то никак.
← →
Lex_! © (2006-06-21 11:18) [5]Select @GUID=newid()
..... та же проблема, запросов ОЧЕНЬ много, не факт что до вставки записи не произойдет генерации идентификатора дважды...
Insert into Table (ID, .....)
Values (@GUID, .....)
или я опять чего - то не понимаю. ..
← →
Ega23 © (2006-06-21 11:24) [6]
> Select @GUID=newid()
> ..... та же проблема, запросов ОЧЕНЬ много, не факт что
> до вставки записи не произойдет генерации идентификатора
> дважды...
> Insert into Table (ID, .....)
> Values (@GUID, .....)
>
> или я опять чего - то не понимаю. ..
>
Я ткбк полный текст привёл. Между Select @GUID=newid() и Insert не должно быть ничего.
← →
Lex_! © (2006-06-21 11:24) [7]Хотя будем надеяться, что все будет ок...
Спасибо, пойду попробую ..
← →
Lex_! © (2006-06-21 11:25) [8]Просто одновременно могут выполняться запросы два одинаковых .. и одновременно в двух получится одинаковый guid
← →
Ega23 © (2006-06-21 11:30) [9]
> Просто одновременно могут выполняться запросы два одинаковых
ЛОЛ
> и одновременно в двух получится одинаковый guid
А это - просто шедевр. GUID он потому GUID и называется.
← →
Lex_! © (2006-06-21 11:33) [10]
> > Просто одновременно могут выполняться запросы два одинаковых
>
>
> ЛОЛ
не вижу ЛОЛа, два человека открывают страницу, выполняется два экземпляра кода, в разных потоках, и одновременно вполне может выполняться и с десяток таких запросов...
GUID всегда дается разный? ...
← →
Val © (2006-06-21 11:34) [11]>[9] Ega23 © (21.06.06 11:30)
функция newid работает как генератор - вне контекста транзакций?
← →
Ega23 © (2006-06-21 11:35) [12]
> не вижу ЛОЛа, два человека открывают страницу, выполняется
> два экземпляра кода, в разных потоках, и одновременно вполне
> может выполняться и с десяток таких запросов...
Запросы не могут выполнятся ОДНОВРЕМЕННО. Как минимум из-за того, что процессор - один. Всегда есть очередь исполнения. Если код в [2] выполнять одним запросов, то хоть миллион пользователей в одну секунду обратятся к БД - всё выполнится строго по очереди.
> GUID всегда дается разный? ...
Естественно.
← →
Ega23 © (2006-06-21 11:38) [13]
> функция newid работает как генератор - вне контекста транзакций?NEWID
Creates a unique value of type uniqueidentifier.
А в констексте транзакции или нет - какая, собственно говоря, разница?
З.Ы. В MSSQL нет генераторов.
← →
Lex_! © (2006-06-21 11:46) [14]
> всё выполнится строго по очереди.
Вообще то винда вроде как многозадачна .. а MSSQL это СУБД которая по идее может обслуживать пользователей одновременно... запросы не будут выполняться строго по очереди .. иначе запросы которые занимают много времени ставили бы в очередь всех остальных .. они выполняются псевдоодновременно .. немножко один немножко другой... хотя спорить... смысл :)
запрос в TADOQuery записал, осталось вытащить значение возвращаемое ... но он почему то пустой... :о\
ЗЫ - на хостинге для базы стоит не однопроцессорный сервер .... так что тут возможность одновременного выполнения думаю не вызывает сомнений.. :)
← →
Lex_! © (2006-06-21 11:49) [15]
> запрос в TADOQuery записал, осталось вытащить значение возвращаемое
> ... но он почему то пустой... :о\
Разобрался.. :)
← →
Ega23 © (2006-06-21 11:53) [16]
> Lex_! © (21.06.06 11:46) [14]
>
>
> > всё выполнится строго по очереди.
>
> Вообще то винда вроде как многозадачна .. а MSSQL это СУБД
> которая по идее может обслуживать пользователей одновременно.
> .. запросы не будут выполняться строго по очереди .. иначе
> запросы которые занимают много времени ставили бы в очередь
> всех остальных .. они выполняются псевдоодновременно ..
> немножко один немножко другой... хотя спорить... смысл :
> )
>
> запрос в TADOQuery записал, осталось вытащить значение возвращаемое
> ... но он почему то пустой... :о\
>
> ЗЫ - на хостинге для базы стоит не однопроцессорный сервер
> .... так что тут возможность одновременного выполнения думаю
> не вызывает сомнений.. :)
Ерунду вы, батенька, говорите. Не считайте разработчиков в Microsoft полными идиотами.
← →
sniknik © (2006-06-21 12:00) [17]> Вообще то винда вроде как многозадачна ...
> ...
неважно все, приведенный блок выполненный одним запросом другими запросами не прервется, и даже более того, будет выполнен в одной транзакции.
можеш проверить к примеру так, выполни одним блоком, типа такого
INSERT INTO Table1 (Field1) VALUES ("Test")
INSERT INTO Table1 (Field2) VALUES ("Test")
причем тут Field1 типа строка (Char(40) к примеру), а Field3 типа INT (вставляем тоже строку(!) чтобы получить ошибку). после выполнения (и ошибки) ищи в таблице в поле Field1 значение "Test", нашол? это потому, что после ошибки транзакция откатилась (самому транзакцию стартовать тут необязательно, будет автоматическая)
> запрос в TADOQuery записал, осталось вытащить значение возвращаемое ... но он почему то пустой... :о\
это знаменитая ошибка "в 17-й строке"!
← →
Lex_! © (2006-06-21 12:08) [18]Всем спасибо, разобрался, вроде...
:)
← →
Lex_! © (2006-06-21 12:17) [19]
> sniknik
Теперь не по теме скажу. Это не то немножко в примере ...
Имелось ввиду что запросы выполняются в разных сессиях, т.е. одновременно можно считать из разных приложений, а в примере два последовательных запроса ... немножко не то ...
> Ega23
Вот именно, в Мелкософте не идиоты, чтобы выполнять запросы по очереди, есть приложения где запросы выполняются до получаса.. хотите сказать что остальные будут ждать пол часа пока выполнится запрос?... Сомневаюсь .. остальные запросы тоже будут выполняться.. :)
← →
Val © (2006-06-21 12:19) [20]>Ega23 © (21.06.06 11:38)
Разница в возможности повторной генерации одного и того же значения для нескольких различных транзакций, в случае отката предыдущих. Т.е не использовался в неудачной - отдали его же опять другой транзакции.
Спасибо, про отсутствие генераторов в МС СКЛ я в курсе.
← →
sniknik © (2006-06-21 12:19) [21]сорри, в проверку ([17]) "закралась" ошибка (пробовал на таблице где одно поле NOT NULL) т.е. оно у меня в любом случае не пишется ни в первую ни во вторую строку, потому и зделал ошибочный вывод о автотранзакци на весь блок...
спасибо подсказали.
← →
Ega23 © (2006-06-21 12:20) [22]
> Теперь не по теме скажу. Это не то немножко в примере ..
> .
> Имелось ввиду что запросы выполняются в разных сессиях,
> т.е. одновременно можно считать из разных приложений, а
> в примере два последовательных запроса ... немножко не то
> ...
Без разницы. Кстати, коли в разных сессиях исполняется, то и ProcessID разный будет. А функция NewID() ВСЕГДА вернёт тебе УНИКАЛЬНЫЙ идентификатор.
> Вот именно, в Мелкософте не идиоты, чтобы выполнять запросы
> по очереди, есть приложения где запросы выполняются до получаса.
> . хотите сказать что остальные будут ждать пол часа пока
> выполнится запрос?... Сомневаюсь .. остальные запросы тоже
> будут выполняться.. :)
Ты бы попробовал и проверил, прежде чем за утверждения кидаться...
← →
Ega23 © (2006-06-21 12:22) [23]
> Разница в возможности повторной генерации одного и того
> же значения для нескольких различных транзакций, в случае
> отката предыдущих. Т.е не использовался в неудачной - отдали
> его же опять другой транзакции.
Насколько мне известно, GUID в один момент времени может быть только один. В другой он будет уже другой.
← →
sniknik © (2006-06-21 12:24) [24]> т.е. одновременно можно считать из разных приложений, а в примере два последовательных запроса ...
> немножко не то ...
пример неправильный, но прерватся один пакет другим, из другой сессии, программы все одно не может. иначе давно уже на "многоюзерских" системах все в коллизиях "захлебнулись" бы.
← →
Val © (2006-06-21 12:26) [25]>[23] Ega23 © (21.06.06 12:22)
да это так, но я не знаю - генерит ли эта функция гуид просто, либо еще занимается какой-то фигней типа "заюзали его или нет", поэтому и спросил на всякий случай. спасибо, не буду флеймить.
← →
Val © (2006-06-21 12:28) [26]>[24] sniknik © (21.06.06 12:24)
в смысле? а "прибивание" пользовательской сессии админом? или мы о разном?
← →
Ega23 © (2006-06-21 12:38) [27]
> да это так, но я не знаю - генерит ли эта функция гуид просто,
> либо еще занимается какой-то фигней типа "заюзали его или
> нет", поэтому и спросил на всякий случай. спасибо, не буду
> флеймить.
Насколько я понимаю, просто генерит и всё.
← →
sniknik © (2006-06-21 12:42) [28]> в смысле? а "прибивание" пользовательской сессии админом? или мы о разном?
а х.з. я уже чегото не уверен ;).
давай "по полкам"
Set NoCount ON
Declare @GUID uniqueidentifier --определили переменную (видимость только в этом пакете "извне" не изменить)
Select @GUID=newid() -- дали переменной значение
Insert into Table (ID, .....) Values (@GUID, .....) -- вставили в таблицу
Set NoCount OFF
Select GUID=@GUID -- вернули переменную
т.е. где бы паралельный поток не вклинился, команду выполнить, на переменную по всему ходу скрипта у него влияния нет (локальнная), чтения из таблицы (последнего значения например после долгих запросов) нет, т.е. то что другой поток может поменять, не используется, а используется локальная переменная которую и записывают и наружу выдают. т.е. прервать процесс не должен.
про админа мысль совсем не понял.
← →
Lex_! © (2006-06-21 12:46) [29]
> т.е. где бы паралельный поток не вклинился, команду выполнить,
> на переменную по всему ходу скрипта у него влияния нет
>
вообще речь шла о том что у переменной в другом потоке возможно будет такое же значение ... но если такого не может быть то вопрос исчерпан.. :)
← →
sniknik © (2006-06-21 12:50) [30]> вообще речь шла о том что у переменной в другом потоке возможно будет такое же значение
ну про то что гуид уникален уже не раз выше говорили, и это не фича mssql (как генератор в IB), это фича системы, т.е. где бы не получил 2 гуида фукцией создания они будут уникальны.
← →
Lex_! © (2006-06-21 12:57) [31]Ага, спасибо, понятно, будем рыть дальше...
ЗЫ - и почему борланд не сделал работу с сессиями в WebBroker"е... :)
← →
Val © (2006-06-21 13:02) [32]>[28] sniknik © (21.06.06 12:42)
а так, под "прерыванием" имелось ввиду что-то типа "грязного чтения"..
ну да, остальным ничего не выгорит, конечно :)
← →
AxelBlack © (2006-06-21 15:42) [33]
> Lex_! © (21.06.06 10:39)
> Доброго времени суток.
> Вопрос собственно: каким образом можно получить только что
> вставленную запись?
>...(с момента вставки записи и до момента выполнения запроса на выборку
>может быть вставлено еще несколько записей... )
Как раз только что закончил тестировать такую же задачу:
Необходимо генерировать уникальный ID int и возвращать клиенту (под MSSQL). Надо - быстро и без ошибок.
Сделал так:
- update и select после него положил в stored procedure одной транзакцией (перформанс (время обработки, или же время затраченное на отправку запроса, его обработку сервером и возвращение результата) достигается тем, что план выполнения помещается в кеш и все происходит на стороне SQL сервера, а не на клиенте)
- вызываю ее через ADOStoredProc с параметрами
Сделал тест с 20 потоками и 1000 вызовов на каждый поток.
Причем:
если в ADOStoredProcedure напрямую задавать ConnectionString
(ConnectionString := fTestGetNextIDTestTable.ADOConnection.ConnectionString), то все ОК, скорость - 6 sec.;
если использовать Connection и задавать в нем один общий ADOConnection
(Connection := fTestGetNextIDTestTable.ADOConnection), то на 20.000 обращений 6 неудачных запросов на новый ID, скорость - намного (!!!) медленнее.
Всего доброго,
Axel
← →
sniknik © (2006-06-21 15:45) [34]> если использовать Connection и задавать в нем один общий ADOConnection
один в разных потоках...? тогда у тебя ошибка на этапе реализации.
← →
Ega23 © (2006-06-21 15:46) [35]
> то все ОК, скорость - 6 sec.;
Скока-скока??????????
← →
Ega23 © (2006-06-21 15:47) [36]
> если использовать Connection и задавать в нем один общий
> ADOConnection
То рано или поздно программа сдохнет при асинхронных запросах.
← →
AxelBlack © (2006-06-21 16:10) [37]
> sniknik © (21.06.06 15:45) [34]
> > если использовать Connection и задавать в нем один общий
> ADOConnection
> один в разных потоках...? тогда у тебя ошибка на этапе реализации.
>
Объясните почему.
Спасибо
← →
sniknik © (2006-06-21 16:16) [38]> Скока-скока??????????
да нормально вроде...
попробовал
таблицаCREATE TABLE t3 (ID INT Identity(1, 1) PRIMARY KEY, Guid uniqueidentifier DEFAULT NEWID())
срипт на запись 20000 (вместо 20 по 1000)SET NOCOUNT ON
DECLARE @I INT
SELECT @I=20000
WHILE (@I > 0)
BEGIN
INSERT INTO t3 DEFAULT VALUES
SELECT @I= @I-1
END
SET NOCOUNT OFF
получилось 6,82 сек (второй вызов 5,46 сек) на моей вовсе не крутой тачке... приличная но...
т.е. - время на более крутой, + время для дробления по потокам... гдето так может и получится.
← →
AxelBlack © (2006-06-21 16:18) [39]
> Ega23 © (21.06.06 15:46) [35]
> > то все ОК, скорость - 6 sec.;
> Скока-скока??????????
Возможно много... Не знаю. В программе-тесте используется синхронизация происходящего в потоках с главной формой + ProcessMessages.
Могу дать код (только ногами не сильно, пожалуйста)
← →
sniknik © (2006-06-21 16:21) [40]> Объясните почему.
потому что без синхронизации нельзя из разных потоков даже с одной переменной работать изза возможных колизий, к обьекту VCL тем более нельзя. не знаю что там может случится, но чтото случится обязательно. (тут както обсуждалось изменение фонта лебела из потока вешало программу на 20 сек. одно! ... а у тебя множественные обращения)
← →
Ega23 © (2006-06-21 16:29) [41]Сорри. Я не так понял. Я почему-то решил, что одна итерация 6 сек выполняется. Оттого и прифигел....
← →
AxelBlack © (2006-06-21 18:03) [42]
> sniknik © (21.06.06 16:21) [40]
Хм-м-м-м.
Я думал иначе.
ADOConnection это не переменная.
Я не до конца вижу участки памяти, которые не защищены от действия множества сторонних потоков (в данном случае!). ADOConnection (в данном случае) используется только для соединения с сервером.
Возможно я ошибаюсь, где-то или везде. Если поправите меня и поясните, буду признателен.
>потому что без синхронизации нельзя из разных потоков даже с одной переменной работать изза возможных колизий, к обьекту VCL тем более нельзя.
В случае VCL, в приложении существует главный thread, который принимает сообщения, адресованные всем компонентам, которыми владеет форма. И если мы вызываем методы какого-либо компонента формы, то достаточно использовать метод потока Synchronize с вызовом необходимого метода, без дополнительных мероприятий по синхронизации.
← →
Ega23 © (2006-06-21 18:10) [43]Если через Synchronize и критические секции - то нафига тогда в разных потоках обращение делать?
← →
sniknik © (2006-06-21 18:22) [44]> то достаточно использовать метод потока Synchronize с вызовом необходимого метода,
> без дополнительных мероприятий по синхронизации.
а что по твоему метод потока Synchronize делает? именно эти дополнительные мероприятия...
ну ладно..., и???? ты использовал? как ты себе вообще это представляеш/сделал? в случае с одним TADOConnection (где? на главной форме/датамодуле?) и кучей TADOCommand/DataSet в разных потоках на него завязанных, каждое выполнение синхронизировал?
ну тоды поздравляю, у тебя все выполнялось в одном потоке, главном, а сами потоки служили лиш для усложнения программинга и расхода времени на взаимодействие/синхронизацию. (имитация бурной деятельности)
если же не делал то наверняка в какуюто коллизию "вляпался".
т.е. куда ни кинь все неправильно в этом случае.
← →
AxelBlack © (2006-06-21 18:45) [45]
> sniknik © (21.06.06 18:22) [44]
> а что по твоему метод потока Synchronize делает? именно
> эти дополнительные мероприятия...
> ну ладно..., и???? ты использовал? как ты себе вообще это
> представляеш/сделал? в случае с одним TADOConnection (где?
> на главной форме/датамодуле?) и кучей TADOCommand/DataSet
> в разных потоках на него завязанных, каждое выполнение синхронизировал?
>
Пожалуйста, не кричи. Давай спокойно обсудим.
На твой вопрос отвечу, что конечно же нет. Synchronize было упомянуто, т.к. мне показалось странным, что "изменение фонта лебела из потока вешало программу на 20 сек", впрочем, детали мне не известны и судить трудно.
Я еще раз повторюсь и сконцентрируюсь на том моменте, который мне кажется сомнительным и который я не до конца понимаю:
"ADOConnection это не переменная.
Я не до конца вижу участки памяти, которые не защищены от действия множества сторонних потоков (в данном случае!). ADOConnection (в данном случае) используется только для соединения с сервером.
Возможно я ошибаюсь, где-то или везде. Если поправите меня и поясните, буду признателен."
Какие в данном случае могут быть коллизии?
Спасибо.
ПС. В данном случае, при использовании Connection := fTestGetNextIDTestTable.ADOConnection на 20.000 вызовов имею несколько подобных сообщений:
Thread 2072: [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied
.......
Thread 3408: [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied
← →
Ega23 © (2006-06-21 18:52) [46]
> ADOConnection (в данном случае) используется только для
> соединения с сервером.
Сколько у тебя коннектов с сервером? Или, если по-другому: сколько ProcessID есть на сервере в момент работы твоей программы?
← →
AxelBlack © (2006-06-21 18:59) [47]
> ну тоды поздравляю, у тебя все выполнялось в одном потоке
Х-м-м-м....
Вот тут надумалось предположение, а не исполнялось ли все это в одном потоке (без использования Synchronize)?
← →
AxelBlack © (2006-06-21 19:04) [48]
> Ega23 © (21.06.06 18:52) [46]
ADOConnection один, значит ProcessID - один.
Сейчас прогнать не могу - позднее скажу. Но почти уверен, что один.
← →
Ega23 © (2006-06-21 19:07) [49]
> ADOConnection один, значит ProcessID - один.
Значит либо всё выполнялось в главном потоке, либо рано или поздно ты наткнёшься на затырки с одновременным доступом к каналу связи.
← →
AxelBlack © (2006-06-21 19:29) [50]
> Ega23 © (21.06.06 18:52) [46]
> Сколько у тебя коннектов с сервером? Или, если по-другому:
> сколько ProcessID есть на сервере в момент работы твоей
> программы?
Гы.
В основном один.
Иногда появляется второй, еще реже появляется третий коннект.
← →
sniknik © (2006-06-21 20:26) [51]> Какие в данном случае могут быть коллизии?
какие угодно. это к разработчикам, у них исходные коды есть... а нам приходится довольствоватся тем, что в хелпе написано "так делать нельзя". точка.
> несколько подобных сообщений:
> Thread 2072: [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied
вот это скорее всего проявление этих самых коллизий.
сделай правильно, с коннектом в каждом потоке и они исчезнут. (по хорошему еще coinitialize в потоке надо вызывать до создания ado компонент)
впрочем ты это уже сделал, второй (или вернее первый описаный) вариант утебя как раз с собственным конектом в каждом потоке. (только конект созданный через строку "неуправляемый" и вся разница)
>> ну тоды поздравляю, у тебя все выполнялось в одном потоке
> Х-м-м-м....
> Вот тут надумалось предположение, а не исполнялось ли все это в одном потоке (без использования Synchronize)?
тебе то чего думать? мое предположение было о твоем коде (потому и предполагал/описывал возможные варианты), а тебе предполагать зачем, просто в исходник посмотри...
← →
Lex_! © (2006-06-22 09:10) [52]Механизм не такой у меня например ... Тут одно приложение и один АдоКоннект, у меня приложение ISAPI и соответственно при например пяти запросах создается пять потоков (и пять экземпляров TAdoConnection) ... но это если пять ..
Хотя я что-то не туда уже.. :)
← →
_MaSteR_NN_ (2006-06-23 11:34) [53]Syntax
@@IDENTITY
Return Types
numeric
Examples
This example inserts a row into a table with an identity column and uses @@IDENTITY to display the identity value used in the new row.
INSERT INTO jobs (job_desc,min_lvl,max_lvl)
VALUES ("Accountant",12,125)
SELECT @@IDENTITY AS "Identity"
Страницы: 1 2 вся ветка
Текущий архив: 2006.09.03;
Скачать: CL | DM;
Память: 0.64 MB
Время: 0.04 c