Topic: GetLastAutoGenValue и MSSQL200
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 01:32 |
|
|
|
|
Приветствую.
Использую D7, AnyDAC 1.12.2., MSSQL2000 (MSDE).
Хронически не работает GetLastAutoGenValue. Делаю "рукотворный" INSERT, строка в таблицу добавляется, затем выполняю GetLastAutoGenValue - возвращает NULL. Внутри GetLastAutoGenValue после oTab.Rows.Count = 1, но возвращает NULL.
При выполнении в Executor-е INSERT-а и SELECT SCOPE_IDENTITY() в log-е пишет SELECT SCOPE_IDENTITY()
...
Unnamed1
Done [78 ms]
|
Executor с последней правкой не пересобирал. Лог из монитора прилагаю. Какие-то там странные BADMEM-ы.
Кстати, может быть у меня что-то с драйверами не то. Explorer при подключении пишет:
================================
Client info
================================
Driver Manager version = 03.52.1117.0000
================================
Session info
================================
Driver name = SQLSRV32.DLL
Driver version = 03.85.1117
Driver conformance = 3
DBMS name = Microsoft SQL Server
DBMS version = 08.00.0194
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 03:39 |
|
|
|
|
|
Заменил SCOPE_IDENTITY() на @@IDENTITY. Теперь работает.
|
|
Diman
Admin
 Admin
| Posts: 1509 |  | Karma: 20 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 04:04 |
|
|
|
|
1) Советую вам вернуться обратно к SCOPE_IDENTITY(). Иначе если у вас есть триггер вставляющий данные в другую таблицу с identity колонкой, то @@IDENTITY будет возвращать именно то значение, а не то, что вы ожидаете получить. Детали - смотрите в MSSQL Books Online.
2) А зачем вам GetLastAutoGenValue ? Может быть все делается проще ?
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 04:23 |
|
|
|
|
Я заменил SCOPE_IDENTITY() на @@IDENTITY не со скуки, а потому, что иначе не работает. Разницу между ними я выяснил перед тем как заменять. В данный момент мне она не критична, хотя я надеюсь, что проблема со SCOPE_IDENTITY как-нибудь разрешится.
Я использую значение автоинкрементного поля как уникальный идентификатор объекта и получаю его сразу после добавления объекта в базу. На MySQL тот же код работает. Если предложите другой работоспособный метод получить значение последнего добавленного автоинкрементного поля - я с удовольствием его использую.
По поводу неработы SELECT SCOPE_IDENTITY() будут комментарии?
PS. С MS SQL 2000 глюков - море. Не до смеха. Кстати, как там проблема с монитором? Его очень не хватает.
|
|
Diman
Admin
 Admin
| Posts: 1509 |  | Karma: 20 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 05:09 |
|
|
|
|
ak wrote: что проблема со SCOPE_IDENTITY как-нибудь разрешится. Проблема в том, что AnyDAC генерирует для Insert & Post запрос:
INSERT INTO TabWithIdentityField (...) VALUES (...); SELECT SCOPE_IDENTITY() AS IdentityField
|
И это работат корректно для ситуаций с тригерами. И SCOPE_IDENTITY()не работает если используется вне такого батча. Вне можно использовать @@IDENTITY, оно может возвратить не то, что ожидается. Так или иначе, в 2.0 будет использоваться SCOPE_IDENTITY для батча и @@IDENTITY вне его.
Если предложите другой работоспособный метод получить значение последнего добавленного автоинкрементного поля - я с удовольствием его использую.
Если вы используете:
ADQuery1.SQL.Text := 'select * from TabWithIdentityField';
ADQuery1.Open;
ADQuery1.Append;
ADQuery1.Fields[1].AsString := 'qweqwe';
ADQuery1.Post;
|
То после Post значение identity поля будет автоматически перечитано. Т.е. просто читайте значение этого поля.
PS. С MS SQL 2000 глюков - море.
Давайте список.
Кстати, как там проблема с монитором? Его очень не хватает.Отвечу отдельным письмом.
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 06:04 |
|
|
|
|
Делаю "рукотворный" INSERT - т.е.:
SQL.Text := 'INSERT...' после выполнения запроса делаю GetLastAutoGenValue
Не пойму, почему это не может работать так как я ожидаю.
Глюки и непонятки пока неисследованные. Могу изложить некоторые в виде жалоб: 1. первое слово запроса не может быть макросом, 2. в UPDATE целочисленному полю не присваивается NULL, 3. можно ли присваивать в UPDATE блобы в MSSQL - не знаю, во всяком случае - не работает, 4. BATCH-INSERT отвергается сервером ('ошибка рядом с INTO') - без монитора не вижу во что разворачивается запрос (а трассировка - вводит в ступор 
Кстати, вычитал в документации про макрос {if (Oracl, TO_CHAR, MSSQL, CONVERT)} Предполагаю, что если оно работает, то можно использовать для TOP-ов и LIMIT-ов ?
|
|
Diman
Admin
 Admin
| Posts: 1509 |  | Karma: 20 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 07:42 |
|
|
|
|
Не пойму, почему это не может работать так как я ожидаю. Потому что, если у таблице X в INSERT будет триггер на вставку и он будет вставлять запись в другую таблицу Y с identity полем, то @@IDENTITY вернет последнее identity для Y а не для X. SQL.Text := 'INSERT...' Используйте:
with ADQuery1 do begin
SQL.Text := 'INSERT INTO ADQA_Identity_tab (descr) VALUES (:P1); SELECT SCOPE_IDENTITY()';
Params[0].AsString := 'asaasa';
Open;
ShowMessage(Fields[0].AsString);
end;
|
1. первое слово запроса не может быть макросом,
Да запросто:
SQL.Text := '&S INTO ADQA_Identity_tab (descr) VALUES (:P1); SELECT SCOPE_IDENTITY()';
Macros[0].AsRaw := 'INSERT';
|
Возможно вы использовали не AsRaw а AsString или иначе.
2. в UPDATE целочисленному полю не присваивается NULL,
3. можно ли присваивать в UPDATE блобы в MSSQL - не знаю, во всяком случае - не работает,Нужен ваш код. Я пробую - присваивается и в 1.12 и в 2.0.
4. BATCH-INSERT отвергается сервером ('ошибка рядом с INTO') - без монитора не вижу во что разворачивается запрос (а трассировка - вводит в ступор В 1.12 не работала обработка ошибок для array execution. Но записи вставлялись. По возможности то же - приведите ваш код.
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 08:08 |
|
|
|
|
Diman wrote: Потому что, если у таблице X в INSERT будет триггер на вставку и он будет вставлять запись в другую таблицу Y с identity полем, то @@IDENTITY вернет последнее identity для Y а не для X. Возможно я недостаточно вразумительно объясняю ситуацию. Поробую все с начала. Забудем про @@IDENTITY.
Делаю "рукотворный" INSERT - т.е.: SQL.Text := 'INSERT...' после выполнения запроса делаю GetLastAutoGenValue Первозданный код GetLastAutoGenValue возвращает NULL. Пробую выполнить в Executor-e последовательность
INSERT ...
SELECT SCOPE_IDENTITY()
|
запись добавляется, SELECT не возвращает ниодной строки.
Вот эту проблему давайте и разберем.
Та же последовательность в EMS SQL Manager выполняется "на Ура".
Используйте:
with ADQuery1 do begin
SQL.Text := 'INSERT INTO ADQA_Identity_tab (descr) VALUES (:P1); SELECT SCOPE_IDENTITY()';
Params[0].AsString := 'asaasa';
Open;
ShowMessage(Fields[0].AsString);
end;
|
Мне бы не хотелось громоздит серверозависивый код на элемантарном инсерте. Хотя, возможно, это будет работать быстрее, чем два отдельных запроса.
Остальное - отдельными постами.
|
|
ak
User
 Expert Boarder
| Posts: 72 |   | Karma: 2 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 08:39 |
|
|
|
|
Diman wrote: 3. можно ли присваивать в UPDATE блобы в MSSQL - не знаю, во всяком случае - не работает,Нужен ваш код. Я пробую - присваивается и в 1.12 и в 2.0.
SQL.Text := 'UPDATE tablename SET BLOB_FIELD = :A0 WHERE ID_FIELD = :A1'
Params[1].AsInteger := A_ID;
Params[0].AsBlob := '';
|
Попадаю в
function TODBCVariable.GetDataPtr(AIndex: SQLUInteger; out ApData: SQLPointer;
out ASize: SQLInteger; out ApInd: PSQLInteger): PSQLPointer;
...
ASSERT((ASize < SQL_LEN_DATA_AT_EXEC_OFFSET) or (ASize >= 0));
|
|
|
Diman
Admin
 Admin
| Posts: 1509 |  | Karma: 20 |
|
Re:GetLastAutoGenValue и MSSQL200
|
|
Posted: 2007/08/09 08:41 |
|
|
|
|
INSERT ... ; SELECT SCOPE_IDENTITY()
|
ADExecutor разбивает это на две команды = два батча. Так как ';' для ADExecutor - разделитель скрипта на команды. Выполните вот это:
-- $DEFINE DELIMITER GO
INSERT INTO ADQA_Identity_tab (descr) VALUES ('zzz');
SELECT SCOPE_IDENTITY()
GO
|
GetLastAutoGenValue
Короче, оставьте @@IDENTITY. С выходом 2.0 проблема отпадет.
|
|
|