Russian Qt Forum
Ноябрь 23, 2024, 23:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Получить значение идентификатора при добавлении строки  (Прочитано 19263 раз)
Tonal
Гость
« Ответ #15 : Ноябрь 19, 2008, 12:02 »

select max(i_key) from table1
это будет не равносильно?
А теперь представь что будет если работают несколько пользователей одновременно...
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #16 : Ноябрь 19, 2008, 20:51 »

Если в пределах транзакции, то все должно быть нормально.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Tonal
Гость
« Ответ #17 : Ноябрь 20, 2008, 09:55 »

Если не вклинится другой поток, хотя тут я не в курсе - можно ли в Qt + ODBC + MS расшаривать транзакцию на несколько потоков.

А по поводу работоспособности QSqlQuery::lastInsertId, нужно дёргать QSqlDriver::hasFeature() и смотреть установлен ли флаг QSqlDriver::LastInsertId.
Записан
Hellraiser
Бывалый
*****
Offline Offline

Сообщений: 451


Просмотр профиля
« Ответ #18 : Ноябрь 20, 2008, 10:18 »

по идее должно. но имхо должна быть табла(или последовательность) отвечающая за генерацию значения.
Так оно и есть. Из системной переменной @@IDENTITY можно получить значение идентификатора, сформированное в результате применения последнего оператора. Наиболее удобный способ - писать процедуру, внутри которой и происходит заполнение полей реальных таблиц.
Очень много интересного можно найти в книге по программированию на MSSQL http://www.axifile.com/?8684781
Записан
spirit
Гость
« Ответ #19 : Ноябрь 20, 2008, 10:29 »

куль, буду знать. с этим сервером никогда не работал Улыбающийся
Записан
roman-ktn
Гость
« Ответ #20 : Ноябрь 20, 2008, 14:04 »

С системной переменной @@IDENTITY заработало
А функция SCOPE_IDENTITY() в qt у меня выводила пустое значение
Всем спасибо
Записан
masha
Гость
« Ответ #21 : Март 16, 2010, 18:56 »

лучше
SELECT IDENT_CURRENT('имя_таблицы')
Записан
IgorK
Гость
« Ответ #22 : Февраль 17, 2012, 14:02 »

С системной переменной @@IDENTITY заработало
А функция SCOPE_IDENTITY() в qt у меня выводила пустое значение
Всем спасибо

Мы не всегда можем использовать INSERT INTO ...; SELECT @@IDENTITY и INSERT INTO ... OUTPUT inserted.id , и никогда не можем их использовать, если б/д создана и используется не нами, т.к. никто не гарантирует, что к таблице не привяжут триггер на вставку:
Код:
SCOPE_IDENTITY and @@IDENTITY will return last identity values generated in any table in the current session. However, SCOPE_IDENTITY returns values inserted only within the current scope; @@IDENTITY is not limited to a specific scope.

For example, you have two tables, T1 and T2, and an INSERT trigger defined on T1. When a row is inserted to T1, the trigger fires and inserts a row in T2. This scenario illustrates two scopes: the insert on T1, and the insert on T2 as a result of the trigger.

Assuming that both T1 and T2 have IDENTITY columns, @@IDENTITY and SCOPE_IDENTITY will return different values at the end of an INSERT statement on T1.

@@IDENTITY will return the last IDENTITY column value inserted across any scope in the current session, which is the value inserted in T2.

SCOPE_IDENTITY() will return the IDENTITY value inserted in T1, which was the last INSERT that occurred in the same scope. The SCOPE_IDENTITY() function will return the NULL value if the function is invoked before any insert statements into an identity column occur in the scope.

Таким образом у нас остается только SCOPE_IDENTITY(), который в отдельном запросе возвращает нам ничего (т.к. для сервера это будет уже другой scope), либо SCOPE_IDENTITY() вернет верное значение, но ODBC драйвер его не вернет (т.к. он не шибко умный), если мы попытаемся выкинуть что-то типа:
Код:
QSqlQuery sql(QSqlDatabase::database());
sql.exec("INSERT INTO someone VALUES (somefings); select SCOPE_IDENTITY()");

Но выход есть: с помощью команды MS SQL EXECUTE() маскируем два запроса "INSERT INTO someone VALUES (somefings)" и "select SCOPE_IDENTITY()" в один и получаем практически безкостыльную рабочую строчку:
Код:
QSqlQuery sql(QSqlDatabase::database());
sql.exec("EXEC('INSERT INTO someone VALUES (somefings); select SCOPE_IDENTITY()')");
sql.next();
int id = sql.value(0).toInt();
« Последнее редактирование: Февраль 17, 2012, 14:47 от IgorK » Записан
RVZ
Гость
« Ответ #23 : Март 19, 2012, 20:16 »

Вообще тема весьма сомнительна...
Добавление строк к в таблицы реляционной БД вопрос весьма не простой и как правило ответственность за это действие передается хранимым процедурам а также процесс удаления строк тоже.
Это связанно с тем что
1) надо обеспечивать корректное добавление с ведением логов, вставкой внешних ключей, вычисляемых столбцов.
2) при изменении структуры таблицы или связей проще править хранимую процедуру чем пере собирать проект и инсталить его на пачке машин.
3) незачем гонять туда сюда промежуточную информацию (вся работа на стороне сервера)
А вот с возвернутом ID записи (после выполнения хранимой процедуры работать просто)
Пример для MS SQL 2005 (есть еще подобный для PostgreSQL)
Код
SQL
CREATE TABLE [my].[Myt](
[MytID] [bigint] IDENTITY(1,1) NOT NULL,
[Surname] [nvarchar](20) NOT NULL,
[FirstName] [nvarchar](20) NOT NULL,
[PersonalTypeID] [smallint] NOT NULL CONSTRAINT [DF_Myt_PersonalTypeID]  DEFAULT ((1)),
[RegistrationDate] [datetime] NOT NULL,
 CONSTRAINT [PK_Myt] PRIMARY KEY CLUSTERED(
[MytID] ASC
 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
 
 
CREATE PROCEDURE [my].[AddRecMyt]
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO my.Myt
(Surname, FirstName, Patronymic, PersonalTypeID, RegistrationDate)
VALUES
('Не определено', 'Не определено', 'Не определено', 1, GETDATE())
SELECT SCOPE_IDENTITY()
END
 

Пример конструктора для формы создания новой записи.
Код
C++ (Qt)
Data::Data(QWidget *parent, int MytID):QWidget(parent),ui(new Ui::Data){
   ui->setupUi(this);
   if(MytID == 0){
       QSqlQuery query;
       query.exec("my.AddRecMyt");
       if(query.first()){
         MytID = query.value(0).toInt();
         qDebug()<<"Add MytID = "<<MytID;
       }
       query.clear();
   }
   ......
}
 

Не совсем по сути вопроса... но может получиться отговорить разработчика Улыбающийся вешать SQL сопли в приложении.
« Последнее редактирование: Март 22, 2012, 10:54 от RVZ » Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.204 секунд. Запросов: 23.