it-swarm.asia

كيف يمكنني استخدام currval () في PostgreSQL للحصول على آخر معرف مدرج؟

لدي طاولة:

CREATE TABLE names (id serial, name varchar(20))

أريد "المعرف المدرج الأخير" من هذا الجدول ، دون استخدام RETURNING id عند الإدراج. يبدو أن هناك وظيفة CURRVAL() ، لكنني لا أفهم كيفية استخدامها.

لقد حاولت مع:

SELECT CURRVAL() AS id FROM names_id_seq
SELECT CURRVAL('names_id_seq')
SELECT CURRVAL('names_id_seq'::regclass)

لكن لا أحد منهم يعمل. كيف يمكنني استخدام currval() للحصول على آخر معرف مدرج؟

70
Jonas

إذا قمت بإنشاء عمود كـ serial يقوم PostgreSQL تلقائيًا بإنشاء تسلسل لذلك.

يتم إنشاء اسم التسلسل تلقائيًا ويكون دائمًا tablename_columnname_seq ، في حالتك سيكون التسلسل أسماء names_id_seq.

بعد الإدراج في الجدول ، يمكنك استدعاء currval() بهذا الاسم التسلسلي:

postgres=> CREATE TABLE names in schema_name (id serial, name varchar(20));
CREATE TABLE
postgres=> insert into names (name) values ('Arthur Dent');
INSERT 0 1
postgres=> select currval('names_id_seq');
 currval
---------
       1
(1 row)
postgres=>

بدلاً من ترميز اسم التسلسل ، يمكنك أيضًا استخدام pg_get_serial_sequence() بدلاً من ذلك:

select currval(pg_get_serial_sequence('names', 'id'));

بهذه الطريقة لا تحتاج إلى الاعتماد على استراتيجية التسمية التي تستخدمها Postgres.

أو إذا كنت لا تريد استخدام اسم التسلسل على الإطلاق ، فاستخدم lastval()

56
a_horse_with_no_name

هذا مباشرة من Stack Overflow

كما أشار إلى ذلكa_horse_with_no_name وJack Douglas ، تعمل currval فقط مع الجلسة الحالية. لذلك إذا كنت موافقًا على حقيقة أن النتيجة قد تتأثر بمعاملة غير ملتزم بها لجلسة أخرى ، ولا تزال تريد شيئًا يعمل عبر الجلسات ، فيمكنك استخدام هذا:

SELECT last_value FROM your_sequence_name;

استخدم الرابط إلى SO لمزيد من المعلومات.

من وثائق Postgres بالرغم من ذلك ، يذكر ذلك بوضوح

من الخطأ استدعاء lastval إذا لم يتم استدعاء nextval بعد في الجلسة الحالية.

لذا أعتقد أن التحدث بدقة من أجل استخدام currval أو last_value بشكل صحيح للتسلسل عبر الجلسات ، هل ستحتاج إلى القيام بشيء من هذا القبيل؟

SELECT setval('serial_id_seq',nextval('serial_id_seq')-1);

بافتراض ، بالطبع ، أنه لن يكون لديك إدخال أو أي طريقة أخرى لاستخدام الحقل التسلسلي في الجلسة الحالية.

53
Slak

أنت تحتاج إلى استدعاء nextval لهذا التسلسل في هذه الجلسة قبل currval :

create sequence serial;
select nextval('serial');
 nextval
---------
       1
(1 row)

select currval('serial');
 currval
---------
       1
(1 row)

لذلك لا يمكنك العثور على "آخر معرّف مدرج" من التسلسل ما لم يتم insert في نفس الجلسة (قد تتراجع المعاملة لكن التسلسل لن يحدث)

كما هو مبين في إجابة a_horse ، create table مع عمود من النوع serial سيقوم تلقائيًا بإنشاء تسلسل واستخدامه في إنشاء القيمة الافتراضية للعمود ، لذلك فإن insert يصل عادةً إلى nextval بشكل ضمني:

create table my_table(id serial);
NOTICE:  CREATE TABLE will create implicit sequence "my_table_id_seq" for 
         serial column "my_table.id"

\d my_table
                          Table "stack.my_table"
 Column |  Type   |                       Modifiers
--------+---------+-------------------------------------------------------
 id     | integer | not null default nextval('my_table_id_seq'::regclass)

insert into my_table default values;
select currval('my_table_id_seq');
 currval
---------
       1
(1 row)
14
Jack says try topanswers.xyz

لذلك هناك بعض المشكلات في هذه الأساليب المختلفة:

يحصل Currval فقط على آخر قيمة تم إنشاؤها في الجلسة الحالية - وهو أمر رائع إذا لم يكن لديك أي شيء آخر يولد القيم ، ولكن في الحالات التي يمكنك فيها استدعاء مشغل و/أو تقدم التسلسل أكثر من مرة في المعاملة الحالية لن تعيد القيمة الصحيحة. هذه ليست مشكلة بالنسبة لـ 99 ٪ من الأشخاص الموجودين - ولكن هذا أمر يجب على المرء أن يأخذ في الاعتبار.

أفضل طريقة للحصول على المعرف الفريد المعين بعد عملية الإدراج هي استخدام عبارة RETURNING. المثال أدناه يفترض أن العمود المرتبط بالتسلسل يسمى "id":

insert into table A (cola,colb,colc) values ('val1','val2','val3') returning id;

لاحظ أن فائدة عبارة RETURNING تتجاوز مجرد الحصول على التسلسل ، لأنها ستقوم أيضًا:

  • قيم الإرجاع التي تم استخدامها لـ "الإدراج النهائي" (بعد ، على سبيل المثال ، ربما يكون مشغل BEFORE قد غير البيانات التي يتم إدراجها.)
  • قم بإعادة القيم التي تم حذفها:

    احذف من الجدول أ حيث المعرف> 100 من العائدين *

  • قم بإعادة الصفوف المعدلة بعد التحديث:

    جدول التحديث مجموعة X = 'y' حيث blah = 'blech' يعود *

  • استخدم نتيجة حذف لتحديث:

    مع A باسم (حذف * من الجدول A كمعرّف إرجاع) ، تم تحديث مجموعة B المحذوفة = true حيث id في (حدد id من A) ؛

3
chander

تحتاج إلى GRANT الاستخدام على المخطط ، مثل هذا:

GRANT USAGE ON SCHEMA schema_name to user;

و

GRANT ALL PRIVILEGES ON schema_name.sequence_name TO user;
1
AMML

إذا كنت ترغب في الحصول على قيمة التسلسل دون استدعاء nextval() ، وبدون الحاجة إلى تعديل التسلسل ، قمت بتجميع دالة PL/pgSQL معًا للتعامل معها: ابحث عن قيمة الكل تسلسل قاعدة البيانات

1
Christophe

اضطررت إلى تنفيذ استعلام على الرغم من استخدام SQLALchemy لأنني لم أكن ناجحًا في استخدام currval.

nextId = db.session.execute("select last_value from <table>_seq").fetchone()[0] + 1

كان هذا python flask + مشروع postgresql.

1
Jalal

في PostgreSQL 11.2 يمكنك التعامل مع التسلسل مثل الجدول الذي يبدو:

مثال إذا كان لديك تسلسل باسم: "names_id_seq"

select * from names_id_seq;
 last_value | log_cnt | is_called
------------+---------+-----------
          4 |      32 | t
(1 row)

يجب أن يمنحك هذا آخر معرف مدرج (4 في هذه الحالة) مما يعني أن القيمة الحالية (أو القيمة التي يجب استخدامها للمعرف التالي) يجب أن تكون 5.

0
scifisamurai