সর্বশেষ sertedোকানো আইডির জন্য পোস্টগ্রিএসকিউএল ফাংশন


321

PostgreSQL এ, আমি কীভাবে একটি টেবিলের মধ্যে শেষ আইডি ?োকানো করব?

এমএস এসকিউএলে রয়েছে SCOPE_IDENTITY ()।

দয়া করে আমাকে এই জাতীয় কিছু ব্যবহার করার পরামর্শ দিবেন না:

select max(id) from table

আপনি সর্বাধিক কার্যকে ঘৃণা করেন কেন? আমি মনে করি এটি খুব সাধারণ। সুরক্ষার মতো কোনও সমস্যা আছে?
jeongmin.cha

9
@ জিয়ংমিন.সি.এইর মধ্যে যদি অন্য অপারেশন রয়েছে এবং আরও সন্নিবেশ (সমবর্তী ক্রিয়াকলাপ) এর মধ্যে সমস্যা রয়েছে তবে সর্বাধিক আইডি পরিবর্তিত হয়েছে, যতক্ষণ না আপনি স্পষ্টভাবে কোনও লক না নিয়ে এবং এটি প্রকাশ না করেন
রোহানগরওয়াল

যদি উদ্দিষ্ট ব্যবহারের ক্ষেত্রে পরবর্তী সন্নিবেশটির মানটির অংশ হিসাবে সর্বশেষ sertedোকানো আইডি ব্যবহার করতে হয় তবে এই প্রশ্নটি দেখুন
ফ্লাক্স

উত্তর:


606

( tl;dr: গোটো অপশন 3: প্রত্যাবর্তনের সাথে অন্তর্ভুক্ত)

মনে রাখবেন যে পোস্টগ্র্যাস্কল-এ টেবিলের জন্য কোনও "আইডি" ধারণা নেই, কেবল সিকোয়েন্সগুলি (যা সাধারণত তবে সেরিয়াল সিউডো টাইপ সহ সারোগেট প্রাথমিক কীগুলির জন্য ডিফল্ট মান হিসাবে ব্যবহৃত হয় না )।

আপনি যদি সদ্য inোকানো সারিটির আইডি পেতে আগ্রহী হন তবে কয়েকটি উপায় রয়েছে:


বিকল্প 1: CURRVAL(<sequence name>);

উদাহরণ স্বরূপ:

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval('persons_id_seq');

ক্রমের নামটি অবশ্যই জানা উচিত, এটি সত্যই স্বেচ্ছাসেবী; এই উদাহরণে আমরা ধরে নিই যে ছকটি সিউডো-টাইপ দিয়ে তৈরি personsএকটি idকলাম তৈরি করেছে SERIAL। এটির উপর নির্ভর না করা এবং আরও পরিষ্কার অনুভব করতে আপনি এর পরিবর্তে ব্যবহার করতে পারেন pg_get_serial_sequence:

  INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John');
  SELECT currval(pg_get_serial_sequence('persons','id'));

ক্যাভ্যাট: একই অধিবেশনটিতেcurrval() কেবল INSERT(যা কার্যকর করা হয়েছে nextval()) পরে কাজ করে ।


বিকল্প 2: LASTVAL();

এটি পূর্ববর্তীগুলির মতো, কেবলমাত্র আপনার সিক্যুয়েন্স নামটি নির্দিষ্ট করার দরকার নেই: এটি সর্বাধিক সাম্প্রতিক পরিবর্তিত অনুক্রমের সন্ধান করে (সর্বদা আপনার সেশনের অভ্যন্তরে, উপরের মতো একই ক্যাভেট)।


CURRVALএবং উভয়ই LASTVALসম্পূর্ণ একযোগে নিরাপদ। পিজিতে ক্রমক্রমের আচরণটি এমনভাবে তৈরি করা হয়েছে যাতে বিভিন্ন অধিবেশন হস্তক্ষেপ না করে, তাই জাতিদের অবস্থার ঝুঁকি নেই (যদি অন্য সেশনটি আমার INSERT এবং আমার নির্বাচনীর মধ্যে অন্য সারি সন্নিবেশ করায় তবে আমি আমার সঠিক মান পাই)।

তবে তাদের একটি সূক্ষ্ম সম্ভাব্য সমস্যা আছে। ডাটাবেসে যদি কিছু ট্রিগার (বা RULE) থাকে যা personsসারণীতে সন্নিবেশ করানোর সাথে সাথে অন্য টেবিলগুলিতে কিছু অতিরিক্ত সন্নিবেশ LASTVALকরায় ... তবে সম্ভবত আমাদের ভুল মান দেবে। সমস্যাটি এমনকি যদি ঘটতে পারে CURRVALতবে একই personsসারণীতে অতিরিক্ত সন্নিবেশ সম্পন্ন করা হলে (এটি স্বাভাবিকের তুলনায় অনেক কম, তবে ঝুঁকিটি এখনও বিদ্যমান)।


বিকল্প 3: INSERTসহRETURNING

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;

এটি আইডি পাওয়ার সবচেয়ে পরিষ্কার, দক্ষ এবং নিরাপদ উপায় efficient এটির আগের কোনও ঝুঁকি নেই।

অপূর্ণতা? প্রায় কোনওটিই নয়: আপনি আপনার ইনসার্ট স্টেটমেন্টটি কল করার উপায়টি সংশোধন করার প্রয়োজন হতে পারে (সবচেয়ে খারাপ ক্ষেত্রে সম্ভবত আপনার এপিআই বা ডিবি স্তর কোনও ইনসার্টের কোনও মান প্রত্যাশা করবে না); এটি স্ট্যান্ডার্ড এসকিউএল নয় (কে চিন্তা করে); এটি পোস্টগ্র্যাস্কিল ৮.২ (ডিসেম্বর ২০০ ... ...) থেকে পাওয়া যায়


উপসংহার: আপনি যদি পারেন তবে 3 বিকল্পের জন্য যান se অন্য কোথাও, 1 টি পছন্দ করুন।

দ্রষ্টব্য: আপনি যদি বিশ্বব্যাপী সর্বশেষ idোকানো আইডিটি পেতে চান (তবে আপনার সেশন দ্বারা প্রয়োজনীয় নয়) এই সমস্ত পদ্ধতি অকেজো less এর জন্য, আপনাকে অবশ্যই অবলম্বন করতে হবে SELECT max(id) FROM table(অবশ্যই, এটি অন্য লেনদেনের অনিয়ন্ত্রিত প্রবেশদ্বারগুলি পড়বে না)।

বিপরীতভাবে, আপনার বিবৃতি দিয়ে সদ্য তৈরি হওয়া আইডিটি পেতে আপনার উপরের 3 টি বিকল্পের পরিবর্তে কখনও ব্যবহার SELECT max(id) FROM tableকরা উচিত নয়INSERT , কারণ (পারফরম্যান্স বাদে) এটি একযোগে নিরাপদ নয়: আপনার INSERTএবং আপনার SELECTঅন্য সেশনের মধ্যে অন্য কোনও রেকর্ড .োকানো থাকতে পারে।


25
লাস্টভাল () খুব খারাপ হতে পারে, আপনি যদি অন্য ট্রিবেলে নিজের উপর সারি সন্নিবেশ করা / ট্রিট চালানোর নিয়ম যোগ করেন।
কাউবার সাপেরেভ

3
SELECT max(id)দুর্ভাগ্যক্রমে আপনি সারিগুলি মোছা শুরু করার সাথে সাথে কাজটি করেন না।
সাইমন এ। ইউগস্টার

2
@ লেওনব্লাই যদি আমি কিছু মিস না করি তবে আপনার যদি আইডি সহ 1,2,3,4,5সারি থাকে এবং 4 এবং 5 টি সারি মুছে ফেলা হয় তবে সর্বশেষ ID োকানো আইডি 5 টি হলেও max()ফিরে আসে
সাইমন এ। ইউগস্টার

9
RETURNING id;অন্য সারণিতে এটি sertোকাতে কীভাবে ব্যবহার করবেন তার একটি নমুনা স্বাগত হবে!
অলিভিয়ার পন্স 21

8
কমান্ড লাইন সরঞ্জামে RETURNING idখাওয়ানো কোনও এসকিউএল স্ক্রিপ্টের মধ্যে আমি কীভাবে ব্যবহার করতে পারি psql?
amoe

82

INSERT বিবৃতিটির প্রত্যাবর্তনের ধারাটি দেখুন । মূলত, INSERT কোয়েরি হিসাবে দ্বিগুণ হয় এবং আপনাকে যে মানটি wasোকানো হয়েছিল তা ফিরিয়ে দেয়।


4
8.2 সংস্করণ হিসাবে কাজ করে এবং এটি সেরা এবং দ্রুত সমাধান।
ফ্রাঙ্ক হাইকেন্স

9
রিটার্নড আইডি কীভাবে ব্যবহার করতে হয় তার একটি দ্রুত ব্যাখ্যা হতে পারে?
অ্যান্ড্রু

@ অ্যান্ড্রু আমি নিশ্চিত না যে আমি প্রশ্নটি বুঝতে পেরেছি। আপনি কি জানেন না যে কীভাবে কোনও ফলাফল থেকে পুনরুদ্ধার করবেন? এটি ভাষা / গ্রন্থাগার নির্ভর করে এবং আপনি কোনও নির্বাচন বা প্রত্যাবর্তন সন্নিবেশ করছেন তা নির্বিশেষে একই কাজ করা উচিত। কেবলমাত্র অন্য যে ব্যাখ্যাটি আমি সামনে আসতে পারি তা হ'ল আপনি কলটি থেকে সাফল্যের সাথে আইডিটি পুনরুদ্ধার করেছেন এবং জানেন না এটি কীসের জন্য ... কোন ক্ষেত্রে আপনি কেন এটি পুনরুদ্ধার করছেন?
কোওয়াতফোর্ড

8
@ অ্যান্ড্রু, আপনি যদি পিএসএইচএল কমান্ড লাইনটি থেকে চালান : insert into names (firstname, lastname) values ('john', 'smith') returning id;তবে এটি select id from names where id=$lastidসরাসরি আইডিকে আউটপুট দেয় যেন আপনি সরাসরি দৌড়েছিলেন । যদি আপনি রিটার্নটিকে আ আ ভেরিয়েবেলে সংরক্ষণ করতে চান , তবে insert into names (firstname, lastname) values ('john', 'smith') returning id into other_variable;যদি রিটার্নিং যুক্ত স্টেটমেন্টটি কোনও ফাংশনের সর্বশেষ বিবৃতি হয় , তবে returningপুরোপুরি ফাংশন দ্বারা আইডি 'এড' প্রদান করা হয়।
আলেকজান্ডার বার্ড

32

আপনি নীচের মতোই INSERT বিবৃতিতে রিটার্নিং ক্লজটি ব্যবহার করতে পারেন

wgzhao=# create table foo(id int,name text);
CREATE TABLE
wgzhao=# insert into foo values(1,'wgzhao') returning id;
 id 
----
  1
(1 row)

INSERT 0 1
wgzhao=# insert into foo values(3,'wgzhao') returning id;
 id 
----
  3
(1 row)

INSERT 0 1

wgzhao=# create table bar(id serial,name text);
CREATE TABLE
wgzhao=# insert into bar(name) values('wgzhao') returning id;
 id 
----
  1
(1 row)

INSERT 0 1
wgzhao=# insert into bar(name) values('wgzhao') returning id;
 id 
----
  2
(1 row)

INSERT 0 

28

লিওনব্লয়ের উত্তর বেশ সম্পূর্ণ। আমি কেবলমাত্র একটি বিশেষ ক্ষেত্রে যুক্ত করব যেখানে কোনও PL / pgSQL ফাংশন থেকে অপশন 3 হুবহু মাপসই করা হয় না যেখানেই শেষ সন্নিবেশিত মানটি পাওয়া দরকার।

উদাহরণস্বরূপ, আমাদের যদি নিম্নলিখিত সারণী থাকে:

CREATE TABLE person(
   id serial,
   lastname character varying (50),
   firstname character varying (50),
   CONSTRAINT person_pk PRIMARY KEY (id)
);

CREATE TABLE client (
    id integer,
   CONSTRAINT client_pk PRIMARY KEY (id),
   CONSTRAINT fk_client_person FOREIGN KEY (id)
       REFERENCES person (id) MATCH SIMPLE
);

আমাদের যদি ক্লায়েন্ট রেকর্ড সন্নিবেশ করতে হয় তবে আমাদের অবশ্যই একজন ব্যক্তির রেকর্ডটি উল্লেখ করতে হবে। তবে ধরা যাক আমরা একটি PL / pgSQL ফাংশন তৈরি করতে চাই যা ক্লায়েন্টে একটি নতুন রেকর্ড সন্নিবেশ করায় তবে নতুন ব্যক্তির রেকর্ড সন্নিবেশ করারও যত্ন নেয় of তার জন্য, আমাদের অবশ্যই লিওনব্লাইয়ের বিকল্প 3 এর সামান্য প্রকরণটি ব্যবহার করতে হবে:

INSERT INTO person(lastname, firstname) 
VALUES (lastn, firstn) 
RETURNING id INTO [new_variable];

নোট করুন যে দুটি INTO ধারা আছে। সুতরাং, পিএল / পিজিএসকিউএল ফাংশনটির সংজ্ঞা দেওয়া হবে:

CREATE OR REPLACE FUNCTION new_client(lastn character varying, firstn character varying)
  RETURNS integer AS
$BODY$
DECLARE
   v_id integer;
BEGIN
   -- Inserts the new person record and retrieves the last inserted id
   INSERT INTO person(lastname, firstname)
   VALUES (lastn, firstn)
   RETURNING id INTO v_id;

   -- Inserts the new client and references the inserted person
   INSERT INTO client(id) VALUES (v_id);

   -- Return the new id so we can use it in a select clause or return the new id into the user application
    RETURN v_id;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

এখন আমরা ব্যবহার করে নতুন ডেটা sertোকাতে পারি:

SELECT new_client('Smith', 'John');

অথবা

SELECT * FROM new_client('Smith', 'John');

এবং আমরা সদ্য নির্মিত আইডি পাই।

new_client
integer
----------
         1

9

যাদের সমস্ত ডেটা রেকর্ড পেতে হবে তাদের জন্য আপনি যুক্ত করতে পারেন

returning *

আপনার ক্যোয়ারির শেষে আইডি সহ সমস্ত বস্তু পেতে।


8

নীচের উদাহরণ দেখুন

CREATE TABLE users (
    -- make the "id" column a primary key; this also creates
    -- a UNIQUE constraint and a b+-tree index on the column
    id    SERIAL PRIMARY KEY,
    name  TEXT,
    age   INT4
);

INSERT INTO users (name, age) VALUES ('Mozart', 20);

তারপরে সর্বশেষ idোকানো আইডি পাওয়ার জন্য এটি সারণী "ব্যবহারকারী" সেক কলামের নাম "আইডি" ব্যবহার করুন

SELECT currval(pg_get_serial_sequence('users', 'id'));

7
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))

অবশ্যই আপনাকে অবশ্যই সারণীর নাম এবং কলামের নাম সরবরাহ করতে হবে।

এটি বর্তমান অধিবেশন / সংযোগের জন্য হবে http://www.postgresql.org/docs/8.3/static/function-sequence.html


1

এটা চেষ্টা কর:

select nextval('my_seq_name');  // Returns next value

যদি এই রিটার্নটি 1 (বা আপনার সিকোয়েন্সের শুরু_মূল্য যাই হোক না কেন), তবে মিথ্যা পতাকাটি পেরিয়ে ক্রমটিকে মূল মানটিতে পুনরায় সেট করুন:

select setval('my_seq_name', 1, false);

তা না হলে,

select setval('my_seq_name', nextValue - 1, true);

এটি সিক্যুয়েন্সের মানটি মূল অবস্থায় পুনরুদ্ধার করবে এবং "সেটওয়াল" আপনি যে সিকোয়েন্স মানটি সন্ধান করছেন তার সাথে ফিরে আসবে।


1

পোস্টগ্রিসের জন্য একই জন্য একটি ইনবিল্ট মেকানিজম রয়েছে, যা একই ক্যোয়ারিতে আইডি প্রদান করে বা আপনি যা চান ক্যোরিটি ফেরত চান। এখানে একটি উদাহরণ। আপনার একটি টেবিল তৈরি হয়েছে তা বিবেচনা করুন যাতে 2 কলাম কলাম 1 এবং কলাম 2 রয়েছে এবং আপনি প্রতিটি সন্নিবেশের পরে কলাম 1 ফিরিয়ে আনতে চান।

# create table users_table(id serial not null primary key, name character varying);
CREATE TABLE
#insert into users_table(name) VALUES ('Jon Snow') RETURNING id;
 id 
----
  1
(1 row)

# insert into users_table(name) VALUES ('Arya Stark') RETURNING id;
 id 
----
  2
(1 row)

0

জাভা এবং পোস্টগ্রিসের সাথে আমার এই সমস্যা ছিল। আমি একটি নতুন সংযোগকারী-জে সংস্করণ আপডেট করে এটি ঠিক করেছি।

PostgreSQL-9.2-1002.jdbc4.jar

https://jdbc.postgresql.org/download.html : সংস্করণ 42.2.12

https://jdbc.postgresql.org/download/postgresql-42.2.12.jar

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.