Михаиллл
МихаилллҚыр. 18, 2019, 8:25 Т.Ж.

Можно ли в SQL при команде Inser узнать id , в который записалось.

Добрый день.
Можно ли при команде Inser узнать id , в который записалось.
Пологаю можно в какое-нибудь поле записать уникальное число и потом по нему искать id, но хотелась бы узнать, есть варианты пологичней и с меньшими затратами системы?
Записываю так

    QSqlQuery query(db);
    query.prepare("insert into UESRS (NAME) "
                  "values (:NAME)");
    query.bindValue(":NAME", "UserNotRegistered");

    if(!query.exec())
    {
        emit sig_error(query.lastError().text());
        qDebug()<<"не записалось";
        qDebug()<<"query.lastError().text() : "<<query.lastError().text();
        msg = "false";
    }
    else {
        qDebug()<<"Ok";
        msg = "true";
    }
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

38
AlexanderBardin
  • Қыр. 18, 2019, 8:29 Т.Ж.

https://docs.microsoft.com/en-us/sql/t-sql/functions/scope-identity-transact-sql?redirectedfrom=MSDN&view=sql-server-2017

    Ruslan Polupan
    • Қыр. 18, 2019, 8:30 Т.Ж.
    • (өңделген)

    CREATE TABLE USERS в студию.
    И вообще для чего используется таблица?
    у меня такая таблица пользователей например:

    --Таблица пользователей
    CREATE TABLE IF NOT EXISTS `users` (
            `user_id`   INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
            `fio`   TEXT NOT NULL,
            `password`  TEXT,
            `isactive`  TEXT NOT NULL DEFAULT 'true'
    );
    
      Михаиллл
      • Қыр. 18, 2019, 8:35 Т.Ж.
      • (өңделген)

      Таблица хранит данные пользователй
      Вот код таблицы:

      CREATE GENERATOR GEN_UESRS_ID;
      
      CREATE TABLE UESRS (
          ID          INTEGER NOT NULL,
          PHONE       CHAR(1024),
          NAME        CHAR(1024),
          "PASSWORD"  CHAR(1024),
          RATING      FLOAT
      );
      
      
      
      
      /******************************************************************************/
      /***                              Primary keys                              ***/
      /******************************************************************************/
      
      ALTER TABLE UESRS ADD PRIMARY KEY (ID);
      

      Еще у ID есть автоинкримент.
      Работа с базой идет в многопоточном режиме.

        Ruslan Polupan
        • Қыр. 18, 2019, 8:56 Т.Ж.

        А что дальше надо делать с id пользователя?

          AlexanderBardin
          • Қыр. 18, 2019, 9:19 Т.Ж.

          Два варианта
          1)
          Если есть поддержка автоинкримента, значит есть тригер и генератор, значит:
          Первым действием получать новый ID например - SELECT GEN_ID( , ) FROM RDB$DATABASE; (пример от СУБД будет отличаться, смотри доку по своей СУБД)
          Далее вставляешь куда угодно, при этом обеспечиваешь уникальность (за этим следит СУБД и дублирования не будет), даже если будет ошибка вставки твой ID просто останется не учтенным, но это без разницы, главная задача уникальности будет обеспечина

          2) Делать вставку и сразу чтение в одной транзакции, т.е. записал данные и прочитал их (с MSSQL так делали, проблем не было)

          А вообще
          - Какая у вас СУБД (от нее зависит много например в MySQL есть команда LAST_INSERT_ID)
          - На чем пишете (Например в Django после сохранении данных сразу можно обратиться и получить ID, без проблем)
          - Задачу бы более шире узнать, т.к. решение может быть проще и вообще лежать в другой плоскости

            Михаиллл
            • Қыр. 18, 2019, 10:01 Т.Ж.

            Я пишу на с++ в Qt.
            База данных Firebird.
            Нужно заргистрировать пользователя без данных, после этого вернуть id, под которым пользователь зарегистрирован. Больше ничего делать не нужно.

              AlexanderBardin
              • Қыр. 18, 2019, 10:09 Т.Ж.

              Вариант 1 используйте - SELECT GEN_ID(my_gen , incr) FROM RDB$DATABASE (https://firebirdsql.org/refdocs/langrefupd20-genid.html)

              Когда пишу под FB делаю именно так, проблем не встречал
              пример таблицы и тригера ниже

              CREATE GENERATOR GEN_USERS_ID;
              
              CREATE TABLE USERS (
                  ID                        DT_ID /* DT_ID = INTEGER NOT NULL */,
                  NAME                      VARCHAR(500),
                  LOGIN                     VARCHAR(50),
                  PWD                       VARCHAR(50),
                  PROF                      VARCHAR(50),
              
              );
              
              
              /******************************************************************************/
              /***                              Primary keys                              ***/
              /******************************************************************************/
              
              ALTER TABLE USERS ADD CONSTRAINT PK_USERS PRIMARY KEY (ID);
              
              
              /******************************************************************************/
              /***                                Indices                                 ***/
              /******************************************************************************/
              
              CREATE INDEX USERS_ID ON USERS (ID);
              CREATE INDEX USERS_NAME ON USERS (NAME);
              
              
              /******************************************************************************/
              /***                                Triggers                                ***/
              /******************************************************************************/
              
              
              
              SET TERM ^ ;
              
              
              
              /******************************************************************************/
              /***                          Triggers for tables                           ***/
              /******************************************************************************/
              
              
              
              /* Trigger: USERS_BI */
              CREATE OR ALTER TRIGGER USERS_BI FOR USERS
              ACTIVE BEFORE INSERT POSITION 0
              as
              begin
                if (new.id is null) then
                  new.id = gen_id(gen_users_id,1);
              end
              ^
              
                Ruslan Polupan
                • Қыр. 18, 2019, 10:40 Т.Ж.

                Думаю если будете делать в потоках то мне кажется что просле INSERT сдулать SELECT u.id FROM users u WHERE u.name = 'UserName' и вернуть Id из потока.

                  AlexanderBardin
                  • Қыр. 18, 2019, 10:49 Т.Ж.

                  Мне кажется плохая идея для FB, впрочем я не знаком с тонкостями работы C++ для MySQL где-то читал там такая фишка работает, но почему-то у меня сложилось мнение что именно MySQL обеспечивает изоляцию. В любом случае по ресурсоемкости будет одно и тоже, мой вариант, он однозначен как топор - будет работать, проблем с уникальностью не будет, а вот с поотками еще вопрос... Только время и нагрузка покажет)

                    Михаиллл
                    • Қыр. 18, 2019, 11:47 Т.Ж.

                    При такой записи имена всех юзеров будут одинаковыми.
                    В таком случае выдаст наверно первый id из базы, а не последний

                    SELECT u.id FROM users WHERE u.name = 'UserName'  
                    
                      AlexanderBardin
                      • Қыр. 18, 2019, 11:50 Т.Ж.

                      вам написали рецепт, если идей лучше нет делайте по рецепту. так как вы написали идентифицировать id нельзя

                        Михаиллл
                        • Қыр. 18, 2019, 11:53 Т.Ж.

                        Да, спасибо буду пытаться сделать по Вашему варианту.

                          AlexanderBardin
                          • Қыр. 18, 2019, 11:58 Т.Ж.

                          у вас два запрлса первый получает id второй вставляет новую запись используя полученный в первом запросе id. Все это вы делаете в С++ так сказать. не забудьте дописать нужный тригер и создать ненератор, если его нет, если делать базу через ibEpert и поставить флаг автоинкримент, то оно все само сделает

                            Михаиллл
                            • Қыр. 18, 2019, 12:08 Т.Қ.

                            Попробовал Ваш запрос

                            SELECT GEN_ID(GEN_UESRS_ID , 1) FROM UESRS
                            

                            Но получаю ошибку

                            value: not positioned on a valid record
                            

                            Скажите пожалуйста что не так в моем запросе?
                            Ниже полный код моей таблицы:

                            /******************************************************************************/
                            /***               Generated by IBExpert 18.09.2019 18:59:25                ***/
                            /******************************************************************************/
                            
                            /******************************************************************************/
                            /***      Following SET SQL DIALECT is just for the Database Comparer       ***/
                            /******************************************************************************/
                            SET SQL DIALECT 3;
                            
                            
                            
                            /******************************************************************************/
                            /***                                 Tables                                 ***/
                            /******************************************************************************/
                            
                            
                            CREATE GENERATOR GEN_UESRS_ID;
                            
                            CREATE TABLE UESRS (
                                ID          INTEGER NOT NULL,
                                PHONE       CHAR(1024),
                                NAME        CHAR(1024),
                                "PASSWORD"  CHAR(1024),
                                RATING      FLOAT
                            );
                            
                            
                            
                            
                            /******************************************************************************/
                            /***                              Primary keys                              ***/
                            /******************************************************************************/
                            
                            ALTER TABLE UESRS ADD PRIMARY KEY (ID);
                            
                            
                            /******************************************************************************/
                            /***                                Triggers                                ***/
                            /******************************************************************************/
                            
                            
                            
                            SET TERM ^ ;
                            
                            
                            
                            /******************************************************************************/
                            /***                          Triggers for tables                           ***/
                            /******************************************************************************/
                            
                            
                            
                            /* Trigger: UESRS_BI */
                            CREATE OR ALTER TRIGGER UESRS_BI FOR UESRS
                            ACTIVE BEFORE INSERT POSITION 0
                            as
                            begin
                              if (new.id is null) then
                                new.id = gen_id(gen_uesrs_id,1);
                            end
                            ^
                            
                            SET TERM ; ^
                            
                            
                            
                            /******************************************************************************/
                            /***                               Privileges                               ***/
                            /******************************************************************************/
                            
                            
                              Михаиллл
                              • Қыр. 18, 2019, 12:49 Т.Қ.

                              А если в базе выполняю эту команду, то получаю 3 числа в столбик, но никак не одно.
                              Скажите пожалуйста, почему так?

                              SELECT GEN_ID(GEN_UESRS_ID , 1) FROM UESRS
                              
                                Михаиллл
                                • Қыр. 18, 2019, 1:05 Т.Қ.

                                Оно похоже пробегает ко всему столбцу и добавляет столько значений, сколько есть в таблице.
                                Если делать так, то добавляет только 1 значение к последнему, но как прописать последнее значение?

                                SELECT GEN_ID(GEN_UESRS_ID , 1) FROM UESRS  WHERE id = 20
                                
                                  AlexanderBardin
                                  • Қыр. 18, 2019, 1:16 Т.Қ.

                                  напишите завтра в телеграмм разберемся, потом тут выложите готовый рецепт @Bardin_A_A

                                    Михаиллл
                                    • Қыр. 19, 2019, 2:45 Т.Ж.

                                    Такой запрос в базе работает

                                    SELECT GEN_ID(GEN_UESRS_ID , 1) FROM RDB$DATABASE
                                    

                                    Но в Qt такой код возвращает 0. Скажите пожалуйста, что не так в этом коде?

                                    query.prepare("SELECT GEN_ID(GEN_UESRS_ID , 1) FROM RDB$DATABASE");
                                    
                                        if(!query.exec())
                                        {
                                            emit sig_error(query.lastError().text());
                                            qDebug()<<"не записалось";
                                            qDebug()<<"query.lastError().text() : "<<query.lastError().text();
                                            msg = "false";
                                        }
                                        else {
                                            qDebug()<<"Ok";
                                            qDebug()<<"query.value(0):"<<query.value(0).toInt();
                                            msg = "true";
                                        }
                                    
                                      Ruslan Polupan
                                      • Қыр. 19, 2019, 2:47 Т.Ж.
                                      • (өңделген)

                                      Процедура не подойдет?

                                      SET TERM ^ ;
                                      CREATE OR ALTER PROCEDURE adduser (name VARCHAR(1024),  phone VARCHAR(1024), password VARCHAR(1024), rating float)
                                      return (user_id integer)
                                      as
                                      DECLARE VARIABLE user_id;
                                      begin
                                          user_id = GEN_ID(GEN_USERS_ID,1);
                                          insert into USERS (ID,PHONE,NAME, PASSWORD,RATING)
                                          values(:user_id, phone, name, password, rating);
                                      end^
                                      SET TERM ; ^
                                      

                                      возвращает id и добавляет запись в таблицу.

                                        Михаиллл
                                        • Қыр. 19, 2019, 3:03 Т.Ж.

                                        Скажите пожалуйста, что делать с это процедурой?
                                        Её нужно выполнить в базе данных и потом как то ее вызывать из Qt? Если да, то как потом вызывать процедуру?

                                          Ruslan Polupan
                                          • Қыр. 19, 2019, 3:24 Т.Ж.
                                          • (өңделген)

                                          Выполнить скрипт на базе через редактор скриптов IBE , а вызывать через QSqlQuery как обычный запрос.
                                          только в доках глянь как получать возвращаемое заначение, я не помню.
                                          q.prepare("execute procedure addser(:name, :ph, :pass, :rat)");

                                            Михаиллл
                                            • Қыр. 19, 2019, 3:32 Т.Ж.

                                            Скажите пожалуйста, как добавить эту процедуру?
                                            Если просто вставляю в скрипт, то оно не работает (что ожидаемо).
                                            Похоже ее нужно добавлять непосредственно в нужную таблицу, но как?

                                              Ruslan Polupan
                                              • Қыр. 19, 2019, 3:39 Т.Ж.

                                              IBexpert Настройки редактор скриптов Ctrl+F12
                                              Не забыть поставить галочку Использовать текщее соединение

                                                AlexanderBardin
                                                • Қыр. 19, 2019, 3:40 Т.Ж.

                                                https://s.mail.ru/BkqS/KQBWcafHa

                                                  AlexanderBardin
                                                  • Қыр. 19, 2019, 3:41 Т.Ж.

                                                  только мне кажется в строке
                                                  3 - returns (user_id integer) нужно написать, а не return
                                                  5 - DECLARE VARIABLE user_id integer; тут по моему надо указать тип переменной integer

                                                    Ruslan Polupan
                                                    • Қыр. 19, 2019, 3:43 Т.Ж.

                                                    Согласен... не было примеров под рукой.

                                                      Михаиллл
                                                      • Қыр. 19, 2019, 3:43 Т.Ж.

                                                      Но у меня почему-то интерфейс отличается, нормально ли это? Или може

                                                        AlexanderBardin
                                                        • Қыр. 19, 2019, 3:47 Т.Ж.

                                                        да нормально, от версии зависит, и у меня все в одном окне опция стоит, у вас нет

                                                          Ruslan Polupan
                                                          • Қыр. 19, 2019, 3:49 Т.Ж.

                                                          Советы по IBE: ВЫМУЧАННЫЕ массой потерянного времени
                                                          1. Использовать последню версию. https://ru.wikipedia.org/wiki/IBExpert в разделе ссылки Бесплатная полнофункциональная версия — Ссылка для скачивания специальной лицензии для бывшего СССР.
                                                          2. НИКОГДА не использовать SDI интерфейс. Изменить можно Настройка Настроки среды.

                                                            Михаиллл
                                                            • Қыр. 19, 2019, 3:58 Т.Ж.

                                                            Получилась такая процедура

                                                            SET TERM ^ ;
                                                            CREATE OR ALTER PROCEDURE adduser (name VARCHAR(1024),  phone VARCHAR(1024), password VARCHAR(1024), rating float)
                                                            returns  (user_id integer)
                                                            as
                                                            DECLARE VARIABLE user_id integer; 
                                                            begin
                                                                user_id = GEN_ID(GEN_USERS_ID,1);
                                                                insert into USERS (ID,PHONE,NAME, PASSWORD,RATING)
                                                                values(:user_id, phone, name, password, rating);
                                                            end^
                                                            SET TERM ; ^
                                                            

                                                            Но при нажатии на выполнение получаю ошибку, говорящую что скрипт выполнен с ошибкой.

                                                              Ruslan Polupan
                                                              • Қыр. 19, 2019, 4 Т.Ж.

                                                              Текст или срин ошибки.

                                                                Михаиллл
                                                                • Қыр. 19, 2019, 4:04 Т.Ж.

                                                                Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements.
                                                                Dynamic SQL Error.
                                                                SQL error code = -901.
                                                                variable USER_ID conflicts with parameter in same procedure.

                                                                  Ruslan Polupan
                                                                  • Қыр. 19, 2019, 4:13 Т.Ж.

                                                                  А если так

                                                                  SET TERM ^ ;
                                                                  CREATE OR ALTER PROCEDURE adduser (name VARCHAR(1024),  phone VARCHAR(1024), password VARCHAR(1024), rating float)
                                                                  returns (out_user_id integer)
                                                                  as
                                                                  DECLARE VARIABLE user_id integer;
                                                                  begin
                                                                      user_id = GEN_ID(GEN_USERS_ID,1);
                                                                      out_user_id = :user_id;
                                                                      insert into USERS (ID,PHONE,NAME, PASSWORD,RATING)
                                                                      values(:user_id, phone, name, password, rating);
                                                                  end^
                                                                  SET TERM ; ^
                                                                  
                                                                    Михаиллл
                                                                    • Қыр. 19, 2019, 4:26 Т.Ж.
                                                                    • Жауап шешім ретінде белгіленді.

                                                                    Подправил скрипт, так приняло:

                                                                    SET TERM ^ ;
                                                                    CREATE OR ALTER PROCEDURE adduser (name VARCHAR(1024),  phone VARCHAR(1024), password VARCHAR(1024), rating float)
                                                                    returns (out_user_id integer)
                                                                    as
                                                                    DECLARE VARIABLE user_id integer;
                                                                    begin
                                                                        user_id = GEN_ID(GEN_UESRS_ID,1);
                                                                        out_user_id = :user_id;
                                                                        insert into UESRS (ID,PHONE,NAME, PASSWORD,RATING)
                                                                        values(:user_id, :phone, :name, :password, :rating);
                                                                    end^
                                                                    SET TERM ; ^
                                                                    

                                                                    В Qt Сделал такой запрос и все заработало

                                                                            query.prepare("execute procedure adduser(:name, :phone, :password, :rating)");
                                                                        query.bindValue(":name", "UserNotRegistered");
                                                                        query.bindValue(":phone", "UserNotRegistered");
                                                                        query.bindValue(":password", "UserNotRegistered");
                                                                        query.bindValue(":rating", 0);
                                                                    
                                                                        if(!query.exec())
                                                                        {
                                                                            emit sig_error(query.lastError().text());
                                                                            qDebug()<<"не записалось";
                                                                            qDebug()<<"query.lastError().text() : "<<query.lastError().text();
                                                                            msg = "false";
                                                                        }
                                                                        else if(query.next()) {
                                                                            qDebug()<<"Ok";
                                                                            qDebug()<<"query.value(0):"<<query.value(0).toString();
                                                                            msg = "true";
                                                                        }
                                                                    

                                                                    Спасибо всем за помощь!

                                                                      Ruslan Polupan
                                                                      • Қыр. 19, 2019, 4:37 Т.Ж.

                                                                      Так а где ты используешь возвращаемый ID?

                                                                        Михаиллл
                                                                        • Қыр. 19, 2019, 4:41 Т.Ж.

                                                                        В клиентской части. Клиентская часть по id будет получать соответствующую информацию.

                                                                          Ruslan Polupan
                                                                          • Қыр. 19, 2019, 5:01 Т.Ж.

                                                                          если просто добавлять запись, то тогда процедра не нужна

                                                                          insert into USERS (ID,PHONE,NAME, PASSWORD,RATING)
                                                                          values(GEN_ID(GEN_USERS_ID,1), phone, name, password, rating);
                                                                          
                                                                            Михаиллл
                                                                            • Қыр. 19, 2019, 5:32 Т.Ж.

                                                                            Но мне же нужно еще получить этот id и вернуть его пользователю, а при таком запросе ничего не вернется.

                                                                              Пікірлер

                                                                              Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                                                                              Кіріңіз немесе Тіркеліңіз
                                                                              Г

                                                                              C++ - Тест 001. Первая программа и типы данных

                                                                              • Нәтиже:66ұпай,
                                                                              • Бағалау ұпайлары-1
                                                                              t

                                                                              C++ - Тест 001. Первая программа и типы данных

                                                                              • Нәтиже:33ұпай,
                                                                              • Бағалау ұпайлары-10
                                                                              t

                                                                              Qt - Тест 001. Сигналы и слоты

                                                                              • Нәтиже:52ұпай,
                                                                              • Бағалау ұпайлары-4
                                                                              Соңғы пікірлер
                                                                              G
                                                                              GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
                                                                              Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
                                                                              d
                                                                              dblas5Шілде 5, 2024, 11:02 Т.Ж.
                                                                              QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                                                              k
                                                                              kmssrАқп. 8, 2024, 6:43 Т.Қ.
                                                                              Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                                                              АК
                                                                              Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
                                                                              Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                                                              Енді форумда талқылаңыз
                                                                              Evgenii Legotckoi
                                                                              Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
                                                                              добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                                                              F
                                                                              FynjyШілде 22, 2024, 4:15 Т.Ж.
                                                                              при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
                                                                              BlinCT
                                                                              BlinCTМаусым 25, 2024, 1 Т.Ж.
                                                                              Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
                                                                              BlinCT
                                                                              BlinCTМамыр 5, 2024, 5:46 Т.Ж.
                                                                              Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
                                                                              Evgenii Legotckoi
                                                                              Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
                                                                              Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

                                                                              Бізді әлеуметтік желілерде бақылаңыз