Форум: "Базы";
Текущий архив: 2006.03.26;
Скачать: [xml.tar.bz2];
ВнизSCOPE_IDENTITY() не всегда корректно выполняется Найти похожие ветки
← →
Serg2103 (2006-02-01 18:11) [0]MS SQL 2005.
Существует программа, которая добавляет в главную таблицу данные. Затем вызывает функцию SCOPE_IDENTITY(), узнает ID только что добавленной строки, затем в другую таблицу добавляет данные, уже привязанные к этому ID.
Вроде все просто и стандартно. Так вот.
Копий этой программы работает одновременно много. И соответственно добавления данных происходить могут одновременно.
Вообщем, стал замечать, что порой (не всегда) функция SCOPE_IDENITY() определяет ID не той строки, которая была добавлена в текущей программе, а какой-то другой, и, соответственно, данные начинают привязыватся не к той строке.
Я чего-то не понимаю? Ведь вроде SCOPE_IDENTITY() должно работать только в пределах текущей сессии, т.е. насколько я могу понять - в пределах текущего подключения. Почему-то это не всегда срабатывает. Подскажите, пожалуйста, в чем может юыть проблема?
← →
Ega23 © (2006-02-01 18:32) [1]
> то порой (не всегда) функция SCOPE_IDENITY() определяет
> ID не той строки, которая была добавлена в текущей программе,
> а какой-то другой, и, соответственно, данные начинают привязыватся
> не к той строке.
Надеюсь, ты это в рамках одной транзакции делаешь? Или несколько запросов с клиента?
← →
Nikolay M. © (2006-02-01 18:46) [2]
> в чем может юыть проблема?
Например, в
> MS SQL 2005.
Я так и не рискнул на него переезжать до выхода первого пака.
← →
Serg2103 (2006-02-01 22:28) [3]
> Надеюсь, ты это в рамках одной транзакции делаешь? Или несколько
> запросов с клиента?
К своему стыду сообщу, что я наверно не совсем хорошо представляю суть вашего вопроса... :[ Вроде, SQL изучил, работать удавалось, а вот в теорию глубоко не вдавался... Наверное, не в рамках одной. Там код примерно так идет:
Query1.SQL.Text:="INSERT ...";
Query1.ExecSQL;
Строчка нейтрального кода
Строчка нейтрального кода
Строчка нейтрального кода
Строчка нейтрального кода
Query1.SQL.Text:="SELECT SCOPE_IDENTITY() AS GUID";
Query1.Open;
GUID:=Query1.FieldByName("GUID").AsString;
Вообщем, вот этот GUID не всегда корректно определяется. Подскажите, в чем моя ошибка?
← →
sniknik © (2006-02-01 23:53) [4]> Там код примерно так идет:
сделай такСтрочка нейтрального кода
Строчка нейтрального кода
Строчка нейтрального кода
Строчка нейтрального кода
ADODataSet1.CommandText:=
"INSERT ..."#13#10+
"SELECT SCOPE_IDENTITY() AS GUID";
ADODataSet1.Open;
GUID:= ADODataSet1.FieldByName("GUID").AsInteger;
так должно быть всегда коректно.
← →
sniknik © (2006-02-01 23:56) [5]но на самом деле поискал бы еще варианты "узких мест" в программе. этот вариант сомнительный какойто.
← →
Fay © (2006-02-02 09:26) [6]2 Nikolay M. © (01.02.06 18:46) [2]
> Надеюсь, ты это в рамках одной транзакции делаешь?
А какая разница?
← →
Ega23 © (2006-02-02 09:46) [7]
> Fay © (02.02.06 09:26) [6]
>
> 2 Nikolay M. © (01.02.06 18:46) [2]
> > Надеюсь, ты это в рамках одной транзакции делаешь?
> А какая разница?
>
А разница такая, что если несколькими запросами это делать, то не факт, что SCOPE_IDENTITY будет нужный. Его может другой клиент "перехватить".
← →
Ega23 © (2006-02-02 09:49) [8]Я бы на твоём месте сделал всё это дело в рамках одной хранимой процедуры.
← →
Fay © (2006-02-02 09:57) [9]2 Ega23 © (02.02.06 09:46) [7]
> А разница такая, что если несколькими запросами это делать, ...
Извините, но я пока не уловил связи между транзакциями и запросами.
← →
Nikolay M. © (2006-02-02 10:14) [10]
> Fay © (02.02.06 09:26) [6]
> 2 Nikolay M. © (01.02.06 18:46) [2]
> > Надеюсь, ты это в рамках одной транзакции делаешь?
> А какая разница?
А зачем ты говоришь это МНЕ?
> Query1.SQL.Text:="INSERT ...";
> Query1.ExecSQL;
> Строчка нейтрального кода
> Строчка нейтрального кода
> Строчка нейтрального кода
> Строчка нейтрального кода
> Query1.SQL.Text:="SELECT SCOPE_IDENTITY() AS GUID";
> Query1.Open;
> GUID:=Query1.FieldByName("GUID").AsString;
Во-первых, хотелось бы увидеть полный текст инсерта и "нейтральные строчки". А, во-вторых, чему равно ADOConnection.KeepConnection?
← →
msguns © (2006-02-02 10:16) [11]>Ega23 © (02.02.06 09:49) [8]
>Я бы на твоём месте сделал всё это дело в рамках одной хранимой процедуры.
А я еще и переставил бы местами запросы: сначала делал бы холостую вставку, определение ID, удаление. После чего вставлял бы мастер-запись с уже известным ID, которое бы и возвращал "клиенту" для добавления в детал или куда там надо (или для перепозиционирования отображаемого НД)
← →
ЮЮ © (2006-02-02 10:21) [12]Thus, two statements are in the same scope if they are in the same stored procedure, function, or batch.
По-моему, SCOPE_IDENTITY здесь неуместно
← →
Fay © (2006-02-02 10:21) [13]2 Nikolay M. © (02.02.06 10:14) [10]
> А зачем ты говоришь это МНЕ?
Могу ли я надеяться, что ТЫ когда-нибудь сможешь простить меня?
← →
Fay © (2006-02-02 10:22) [14]2 ЮЮ © (02.02.06 10:21) [12]
Совершенно верно
← →
Nikolay M. © (2006-02-02 10:24) [15]
> Fay © (02.02.06 10:21) [13]
Я не настолько жесток, чтобы отнимать у человека надежду.
> Могу ли я надеяться
Да! Конечно.
> ТЫ когда-нибудь сможешь простить меня?
НЕТ!
:-)))
← →
Serg2103 (2006-02-02 11:04) [16]
> Во-первых, хотелось бы увидеть полный текст инсерта и "нейтральные
> строчки". А, во-вторых, чему равно ADOConnection.KeepConnection?
>
Такой вот код:
Query3.SQL.Text:=Trim(AnsiReplaceText(Format("INSERT INTO %s.dbo.News (SiteID, ClippingID, NewsTitle, NewsCreateDate, NewsTrueCreateDate, NewsFindDate, NewsURL) VALUES (""%s"", ""%s"", ""%s"", ""%s"", ""%s"", ""%s"", ""%s"")", [Base+TableDatePrist(CurNews.NewsDate), Mainform.SiteID, CurClippingID, Kav(CurNews.NewsTitle), CurNews.NewsDate, TrueNewsDate, CurNews.NewsFindDate, CurURL]), #13#10, " "));
Query3.ExecSQL;
Query3.SQL.Text:="SELECT SCOPE_IDENTITY() as NewsID";
Query3.Open;
MonthNewsID:=Query3.FieldByName("NewsID").AsString;
Объяснять, что вставляется - думаю не принципиально. INSERT корректный.
На самом деле, вчера, когда писал, кода под рукой не было - потому и не выложил. Сейчас вижу, что между двумя запросами - "нейтрального" кода нет.
KeepConnection у TADOConnection включен.
← →
Fay © (2006-02-02 11:08) [17]2 Serg2103 (01.02.06 22:28) [3]
Никаких ExecSQL. Просто Open дляset nocount on
insert....
select SCOPE_IDENTITY() as NewsID
← →
ЮЮ © (2006-02-02 11:09) [18]Ну и что мешает SELECT SCOPE_IDENTITY добавить в тот же пакет, где производится INSERT? Почему предпочитаешь отдельно?
← →
Nikolay M. © (2006-02-02 11:10) [19]
> SCOPE_IDENTITY()
Замени на @@IDENTITY
← →
Fay © (2006-02-02 11:14) [20]2 Nikolay M. © (02.02.06 11:10) [19]
Такая замена не совсем корректна. SCOPE_IDENTITY() и @@IDENTITY возвращают разные значения (в общем случае).
← →
Nikolay M. © (2006-02-02 11:26) [21]
> SCOPE_IDENTITY() и @@IDENTITY возвращают разные значения
> (в общем случае).
Конечно. Если есть тригеры. Если их нет, то сойдет.
Но самое правильное, конечно - это [17].
← →
sniknik © (2006-02-02 11:34) [22]нет, самое правильное это [4] т.к. это тоже самое но основано на " более правильном" компаненте.
← →
Fay © (2006-02-02 11:37) [23]2 sniknik © (02.02.06 11:34) [22]
Ой, я и не заметил [4]...
А что все тогда обсуждают? 8)
← →
Nikolay M. © (2006-02-02 12:16) [24]
> sniknik © (02.02.06 11:34) [22]
> нет, самое правильное это [4] т.к. это тоже самое но основано
> на " более правильном" компаненте
КомпАнент здесь - дело десятое. Если скажешь, чем ADOQuery в данном случае "лучше" ADODataSet, буду рад узнать что-то новое.
Зато у тебя нет SET NOCOUNT ON, а в [17] он есть, и это более правильно, чем когда его нет, но компАнент "правильный" :)
← →
sniknik © (2006-02-02 12:23) [25]> Если скажешь, чем ADOQuery в данном случае "лучше" ADODataSet, буду рад узнать что-то новое.
вериш, уже устал это пояснять и чтото доказывать. может хоть ктото просто поверить на слово? или сделать поиск раз уж "буду рад узнать что-то новое" (в дайджестах например), или посмотреть в исходники ADODB сам?
> Зато у тебя нет SET NOCOUNT ON
DataSet сам пропустит "пустышки" передваряющие наполненный рекордсет. особого смысла здесь в нем нет.
← →
Nikolay M. © (2006-02-02 13:18) [26]
> sniknik © (02.02.06 12:23) [25]
> вериш, уже устал это пояснять и чтото доказывать. может
> хоть ктото просто поверить на слово? или сделать поиск раз
> уж "буду рад узнать что-то новое" (в дайджестах например),
> или посмотреть в исходники ADODB сам?
Верю, что устал, потому что постоянно наблюдаю твою нелюбовь к ADOQuery и прочим производным :)
Честно говоря, разбираться в вопросе пока не было времени, потому что всегда пользуюсь ADOCommand и ADODataSet.
← →
msguns © (2006-02-02 13:52) [27]>Nikolay M. ©
Ты, Коля, эта.. не спорь с профессором. Все равно в дурнях оставит, вот увидишь ;))
← →
Nikolay M. © (2006-02-02 14:56) [28]
> msguns © (02.02.06 13:52) [27]
Я этого... буду заниматься тем, чем сочту нужным. Хоть профессоров в дураках оставлять, хоть наоборот...
← →
Shirson © (2006-02-03 13:57) [29]Из года в год тема SCOPE_IDENTITY() и @@IDENTITY поднимается с завидной постоянностью и мигрирует из темы в тему. Почему перед использованием той или иной методы вопрошающие не сомотрят в T_SQL Help, который можно вызвать из меню Query Analiser, совершенно загадочно.
Serg2103, для отлова последнего вставленного identity в таблицу, как верно заметили, следует смотреть SCOPE_IDENTITY() в том же запросе, в котором и производится insert. В идеале, на сервере создаётся SP, в которую передаются параметры для insert, а результатом возвращается identity. В случае динамического формирования запроса, его тоже можно передавать в SP и получать identity, а если не хочется извращаться, то делать как в [17].
Если же вам необходимо получать последний identity, который был вставлен в конкретную таблицу, незваисимо от того, кем и когда это было сделанно, стоит обратить внимание на IDENT_CURRENT.
P.S. И еще, Serg2103, мой вам совет. Потрате немного времени на хелп по T_SQL и постигните Дзен такой прекрасной вещи какADOQuery.Parameters.ParamValues
. Тогда такие ужасы и катастрофы какAnsiReplaceText(Format("INSERT INTO %s...
навсегда уйдут из вашей жизни :)
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2006.03.26;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.04 c