Здравствуйте! По Oracle не силён. Соединяюсь с БД через PDO и есть метод PDO::lastInsertId. В документации написано, что если драйвер не поддерживает этот метод, то будет вызвана ошибка IM001 SQLSTATE. Драйвер для Oracle не поддерживает этот метод. Есть ли аналого этого метода, чтобы при INSERT получать идентификатор текущей записи и не делать SELECT на получение ID текущей записи?
Если мне не изменяет память, то Оракловые конструкции позволяют делать INSERT INTO ..... RETURNING .. То есть вы можете вернуть результат инкрементированного ключа/индекса или чего там у вас.
В Oracle для генерации уникальных ключей используются последовательности(sequence). Для генерации ключа служит конструкция название последовательности.NEXTVAL.Таким образом, чтобы получить код вставленной записи нужно выполнить запрос insert into table name (id,name,.. ) values (название последовательности.NEXTVAL,'gghh',..) RETURNING ID INTO NewId. Для дальнейшего изучения поищи: oracle sequence nextval RETURNING
Спасибо за ответы. Да, я также наткнулся на RETURNING, но я пока не могу решить проблему его использования. Выполняю SQL-скрипт в Home -> SQL Workshop -> SQL Commands (Web-панель Oracle) Код (Text): INSERT INTO tbl (id, first_name, ....) VALUES(users_seq.NEXTVAL, 'иван', ...) RETURNING id INTO :ID Появляется модальное окно, в котором нужно заполнить поле ":ID". И только после этого запись вставляется. Выполняю SQL-запрос Код (Text): INSERT INTO tbl (id, first_name, ....) VALUES(users_seq.NEXTVAL, 'иван', ...) RETURNING ID INTO NewID получаю ответ Выполняю SQL-запрос Код (Text): INSERT INTO tbl (id, first_name, ....) VALUES(users_seq.NEXTVAL, 'иван', ...) RETURNING ID получаю ответ Выполненяю запрос в PHP Код (Text): INSERT INTO tbl (id, first_name, ....) VALUES(users_seq.NEXTVAL, 'иван', ...) RETURNING id INTO :ID И запись добавляется только после того, как в :ID передаю любое случайное число и в ответ ничего не приходит. Я так понимаю, что RETURNING id аналогично SELECT users_seq.CURVAL FROM tbl?
Сам я не силен в Oracle, но то что прочитал сводится к следующему: в коде Код (Text): INSERT INTO tbl (id, first_name, ....) VALUES(users_seq.NEXTVAL, 'иван', ...) RETURNING id INTO :NewID NewID это название переменной. Так что сначала нужно написать хранимую процедуру вставки новой записи и определить в ней эту переменную. Ну и далее использовать эту процедуру для вставки. Так что проще просто получить значение id и потом использовать в запросе вставки новой записи: select users_seq.NEXTVAL from dual
runner, нах не надо процедуру. ради каждого инсерта процедуру городить слишком жирно будет. максимум окружить sql-выражение блочными скобками begin - end топикстартер пишет, что пытается применить insert-returning но с получением нового значения проблемы. я спрашиваю ЕГО: как ты вызываешь запрос на выполнение, как привязываешь переменную? это уже относится не к синтаксису Oracle, а к интерфейсу PDO
Да, действительно это уже излишества писать ещё один триггер. Тогда уж лучше обычный SELECT выполнить. Нет. Собственно сам PHP код в изначальном виде: Код (Text): $post = array( 'first_name' => 'Name', 'last_name' => 'Surname', 'mobile_phone' => 9133333333, 'email' => 'mail@domain.com' ); $sth = $dbh->prepare('INSERT INTO users (first_name, last_name, mobile_phone, email) VALUES(:first_name, :last_name, :mobile_phone, :email)'); $sth->execute($post); Код с использованием RETURNING id INTO :ID: Код (Text): $post = array( 'first_name' => 'Name', 'last_name' => 'Surname', 'mobile_phone' => 9133333333, 'email' => 'mail@domain.com', 'id' => rand(1,99999999) ); $sth = $dbh->prepare('INSERT INTO users (id, first_name, last_name, mobile_phone, email) VALUES(users_seq.NEXTVAL, :first_name, :last_name, :mobile_phone, :email) RETURNING id INTO :ID'); $sth->execute($post);
Всем спасибо. Ответ на проблему нашёл коллега, спасибо ему за это. Почему то после сохранения адрес меняется на Ответ здесь Код (Text): /* This is an example of returning the primary key from an insert so that you can do inserts on other tables with foreign keys based on that value. The date is just used to provied semi-unique data to be inserted.*/ $conn = oci_connect("username", "password") $stmt = oci_parse($conn, "INSERT INTO test (test_msg) values (:data) RETURN test_id INTO :RV"); $data = date("d-M-Y H:i:s"); oci_bind_by_name($stmt, ":RV", $rv, -1, SQLT_INT); oci_bind_by_name($stmt, ":data", $data, 24); oci_execute($stmt); print $rv; Я правда не проверял эту реализацию под PDO, но думаю проблем не будет.
вот и хорошо. а в PDO для входящих параметров подходит bindValue() а для возвращаемых bindParam() http://www.php.ru/manual/pdostatement.bindparam.html offtopic: да уж, сдешний парсер bbcode делает всё, чтобы испортить ссылки на оригинальный мануал )))
Решил всё таки поставленную задачу средствами PDO. Ну и кому-то это может быть полезным. Код (Text): $sth = $dbh->prepare('INSERT INTO users (first_name, last_name) VALUES (:first_name, :last_name) RETURN id INTO :newID'); $sth->bindValue(':first_name', $first_name, PDO::PARAM_STR); $sth->bindValue(':last_name', $last_name, PDO::PARAM_STR); // Указываем что $id – это параметр INOUT для хранимой процедуры // 10 - это длина типа данных // Чтобы указать, что $id это параметр OUT хранимой процедуры необходимо явно задать длину! $sth->bindParam(':newID', $id, PDO::PARAM_INT|PDO::PARAM_INPUT_OUTPUT, 10); $sth->execute(); echo $id;