Михаиллл
Михаиллл18. September 2019 08: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
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

38
AlexanderBardin
  • 18. September 2019 08:29

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

    Ruslan Polupan
    • 18. September 2019 08:30
    • (bearbeitet)

    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. September 2019 08:35
      • (bearbeitet)

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

      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. September 2019 08:56

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

          AlexanderBardin
          • 18. September 2019 09:19

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

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

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

            Михаиллл
            • 18. September 2019 10:01

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

              AlexanderBardin
              • 18. September 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. September 2019 10:40

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

                  AlexanderBardin
                  • 18. September 2019 10:49

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

                    Михаиллл
                    • 18. September 2019 11:47

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

                    SELECT u.id FROM users WHERE u.name = 'UserName'  
                    
                      AlexanderBardin
                      • 18. September 2019 11:50

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

                        Михаиллл
                        • 18. September 2019 11:53

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

                          AlexanderBardin
                          • 18. September 2019 11:58

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

                            Михаиллл
                            • 18. September 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. September 2019 12:49

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

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

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

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

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

                                    Михаиллл
                                    • 19. September 2019 02: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. September 2019 02:47
                                      • (bearbeitet)

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

                                      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. September 2019 03:03

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

                                          Ruslan Polupan
                                          • 19. September 2019 03:24
                                          • (bearbeitet)

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

                                            Михаиллл
                                            • 19. September 2019 03:32

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

                                              Ruslan Polupan
                                              • 19. September 2019 03:39

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

                                                AlexanderBardin
                                                • 19. September 2019 03:40

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

                                                  AlexanderBardin
                                                  • 19. September 2019 03:41

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

                                                    Ruslan Polupan
                                                    • 19. September 2019 03:43

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

                                                      Михаиллл
                                                      • 19. September 2019 03:43

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

                                                        AlexanderBardin
                                                        • 19. September 2019 03:47

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

                                                          Ruslan Polupan
                                                          • 19. September 2019 03:49

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

                                                            Михаиллл
                                                            • 19. September 2019 03: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. September 2019 04:00

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

                                                                Михаиллл
                                                                • 19. September 2019 04: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. September 2019 04: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. September 2019 04:26
                                                                    • Die Antwort wurde als Lösung markiert.

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

                                                                    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. September 2019 04:37

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

                                                                        Михаиллл
                                                                        • 19. September 2019 04:41

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

                                                                          Ruslan Polupan
                                                                          • 19. September 2019 05:01

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

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

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

                                                                              Kommentare

                                                                              Nur autorisierte Benutzer können Kommentare posten.
                                                                              Bitte Anmelden oder Registrieren
                                                                              Letzte Kommentare
                                                                              ИМ
                                                                              Игорь Максимов5. Oktober 2024 07:51
                                                                              Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                                                                              d
                                                                              dblas55. Juli 2024 11:02
                                                                              QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                                                                              k
                                                                              kmssr8. Februar 2024 18:43
                                                                              Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
                                                                              Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
                                                                              EVA
                                                                              EVA25. Dezember 2023 10:30
                                                                              Boost - statisches Verknüpfen im CMake-Projekt unter Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
                                                                              Jetzt im Forum diskutieren
                                                                              J
                                                                              JacobFib17. Oktober 2024 03:27
                                                                              добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
                                                                              JW
                                                                              Jhon Wick1. Oktober 2024 15:52
                                                                              Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
                                                                              КГ
                                                                              Кирилл Гусарев27. September 2024 09:09
                                                                              Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
                                                                              F
                                                                              Fynjy22. Juli 2024 04:15
                                                                              при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

                                                                              Folgen Sie uns in sozialen Netzwerken