Михаиллл
МихаилллSept. 18, 2019, 8:25 a.m.

Можно ли в 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";
    }
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

38
AlexanderBardin
  • Sept. 18, 2019, 8:29 a.m.

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

    Ruslan Polupan
    • Sept. 18, 2019, 8:30 a.m.
    • (edited)

    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'
    );
    
      Михаиллл
      • Sept. 18, 2019, 8:35 a.m.
      • (edited)

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

      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
        • Sept. 18, 2019, 8:56 a.m.

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

          AlexanderBardin
          • Sept. 18, 2019, 9:19 a.m.

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

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

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

            Михаиллл
            • Sept. 18, 2019, 10:01 a.m.

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

              AlexanderBardin
              • Sept. 18, 2019, 10:09 a.m.

              Вариант 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
                • Sept. 18, 2019, 10:40 a.m.

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

                  AlexanderBardin
                  • Sept. 18, 2019, 10:49 a.m.

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

                    Михаиллл
                    • Sept. 18, 2019, 11:47 a.m.

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

                    SELECT u.id FROM users WHERE u.name = 'UserName'  
                    
                      AlexanderBardin
                      • Sept. 18, 2019, 11:50 a.m.

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

                        Михаиллл
                        • Sept. 18, 2019, 11:53 a.m.

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

                          AlexanderBardin
                          • Sept. 18, 2019, 11:58 a.m.

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

                            Михаиллл
                            • Sept. 18, 2019, 12:08 p.m.

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

                            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                               ***/
                            /******************************************************************************/
                            
                            
                              Михаиллл
                              • Sept. 18, 2019, 12:49 p.m.

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

                              SELECT GEN_ID(GEN_UESRS_ID , 1) FROM UESRS
                              
                                Михаиллл
                                • Sept. 18, 2019, 1:05 p.m.

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

                                SELECT GEN_ID(GEN_UESRS_ID , 1) FROM UESRS  WHERE id = 20
                                
                                  AlexanderBardin
                                  • Sept. 18, 2019, 1:16 p.m.

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

                                    Михаиллл
                                    • Sept. 19, 2019, 2:45 a.m.

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

                                    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
                                      • Sept. 19, 2019, 2:47 a.m.
                                      • (edited)

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

                                      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 и добавляет запись в таблицу.

                                        Михаиллл
                                        • Sept. 19, 2019, 3:03 a.m.

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

                                          Ruslan Polupan
                                          • Sept. 19, 2019, 3:24 a.m.
                                          • (edited)

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

                                            Михаиллл
                                            • Sept. 19, 2019, 3:32 a.m.

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

                                              Ruslan Polupan
                                              • Sept. 19, 2019, 3:39 a.m.

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

                                                AlexanderBardin
                                                • Sept. 19, 2019, 3:40 a.m.

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

                                                  AlexanderBardin
                                                  • Sept. 19, 2019, 3:41 a.m.

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

                                                    Ruslan Polupan
                                                    • Sept. 19, 2019, 3:43 a.m.

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

                                                      Михаиллл
                                                      • Sept. 19, 2019, 3:43 a.m.

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

                                                        AlexanderBardin
                                                        • Sept. 19, 2019, 3:47 a.m.

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

                                                          Ruslan Polupan
                                                          • Sept. 19, 2019, 3:49 a.m.

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

                                                            Михаиллл
                                                            • Sept. 19, 2019, 3:58 a.m.

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

                                                            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
                                                              • Sept. 19, 2019, 4 a.m.

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

                                                                Михаиллл
                                                                • Sept. 19, 2019, 4:04 a.m.

                                                                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
                                                                  • Sept. 19, 2019, 4:13 a.m.

                                                                  А если так

                                                                  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 ; ^
                                                                  
                                                                    Михаиллл
                                                                    • Sept. 19, 2019, 4:26 a.m.
                                                                    • The answer was marked as a solution.

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

                                                                    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
                                                                      • Sept. 19, 2019, 4:37 a.m.

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

                                                                        Михаиллл
                                                                        • Sept. 19, 2019, 4:41 a.m.

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

                                                                          Ruslan Polupan
                                                                          • Sept. 19, 2019, 5:01 a.m.

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

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

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

                                                                              Comments

                                                                              Only authorized users can post comments.
                                                                              Please, Log in or Sign up
                                                                              AD

                                                                              C ++ - Test 004. Pointers, Arrays and Loops

                                                                              • Result:50points,
                                                                              • Rating points-4
                                                                              m

                                                                              C ++ - Test 004. Pointers, Arrays and Loops

                                                                              • Result:80points,
                                                                              • Rating points4
                                                                              m

                                                                              C ++ - Test 004. Pointers, Arrays and Loops

                                                                              • Result:20points,
                                                                              • Rating points-10
                                                                              Last comments
                                                                              ИМ
                                                                              Игорь МаксимовNov. 22, 2024, 7:51 p.m.
                                                                              Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                                                                              Evgenii Legotckoi
                                                                              Evgenii LegotckoiOct. 31, 2024, 9:37 p.m.
                                                                              Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                                                                              A
                                                                              ALO1ZEOct. 19, 2024, 3:19 p.m.
                                                                              Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                                                                              ИМ
                                                                              Игорь МаксимовOct. 5, 2024, 2:51 p.m.
                                                                              Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                                                              d
                                                                              dblas5July 5, 2024, 6:02 p.m.
                                                                              QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                                                              Now discuss on the forum
                                                                              Evgenii Legotckoi
                                                                              Evgenii LegotckoiJune 24, 2024, 10:11 p.m.
                                                                              добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                                                                              t
                                                                              tonypeachey1Nov. 15, 2024, 2:04 p.m.
                                                                              google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                                                                              NSProject
                                                                              NSProjectJune 4, 2022, 10:49 a.m.
                                                                              Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                                                                              9
                                                                              9AnonimOct. 25, 2024, 4:10 p.m.
                                                                              Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

                                                                              Follow us in social networks