PostgreSQL में, मुझे अंतिम आईडी तालिका में सम्मिलित कैसे करनी है?
MS SQL में SCOPE_IDENTITY () है।
कृपया मुझे ऐसा कुछ उपयोग करने की सलाह न दें:
select max(id) from table
PostgreSQL में, मुझे अंतिम आईडी तालिका में सम्मिलित कैसे करनी है?
MS SQL में SCOPE_IDENTITY () है।
कृपया मुझे ऐसा कुछ उपयोग करने की सलाह न दें:
select max(id) from table
जवाबों:
(( tl;dr
गोटो ऑप्शन 3: INSERT with RETURNING)
याद PostgreSQL में तालिकाओं के लिए कोई "आईडी" अवधारणा है कि वहाँ, बस दृश्यों (जो आमतौर पर लेकिन नहीं कर रहे हैं जरूरी साथ, किराए की प्राथमिक कुंजी के लिए डिफ़ॉल्ट मान के रूप में इस्तेमाल बम छद्म प्रकार)।
यदि आप एक नई सम्मिलित पंक्ति की आईडी प्राप्त करने में रुचि रखते हैं, तो कई तरीके हैं:
विकल्प 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 और मेरे चयन के बीच एक और पंक्ति सम्मिलित करता है, तो मुझे अभी भी अपना सही मूल्य मिलता है)।
हालांकि उनके पास एक सूक्ष्म संभावित समस्या है। यदि डेटाबेस में कुछ TRIGGER (या RULE) हैं, जो persons
तालिका में सम्मिलित करने पर , अन्य तालिकाओं में कुछ अतिरिक्त सम्मिलन करता है ... तो LASTVAL
शायद हमें गलत मान देगा। समस्या तब भी हो सकती है CURRVAL
, यदि अतिरिक्त प्रविष्टि एक ही persons
तालिका में की जाती है (यह बहुत कम सामान्य है, लेकिन जोखिम अभी भी मौजूद है)।
विकल्प 3: के INSERT
साथRETURNING
INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
यह आईडी प्राप्त करने का सबसे साफ, कुशल और सुरक्षित तरीका है। इसमें पहले के कोई भी जोखिम नहीं हैं।
कमियां? लगभग कोई नहीं: आपको अपने INSERT स्टेटमेंट को कॉल करने के तरीके को संशोधित करने की आवश्यकता हो सकती है (सबसे खराब स्थिति में, शायद आपकी API या DB परत किसी INSERT से कोई मान वापस करने की उम्मीद नहीं करती है); यह मानक SQL नहीं है (जो परवाह करता है); यह Postgresql 8.2 (Dec 2006 ...) के बाद से उपलब्ध है
निष्कर्ष: यदि आप कर सकते हैं, तो विकल्प 3 पर जाएं। कहीं और, 1 को प्राथमिकता दें।
नोट: यदि आप विश्व स्तर पर अंतिम सम्मिलित आईडी प्राप्त करने का इरादा नहीं रखते हैं (तो जरूरी नहीं कि आपके सत्र से) ये सभी विधियां बेकार हैं । इसके लिए, आपको SELECT max(id) FROM table
(निश्चित रूप से, यह अन्य लेनदेन से अप्रयुक्त आवेषण नहीं पढ़ा जाएगा) का सहारा लेना चाहिए ।
इसके विपरीत, आपको ऊपर दिए गए 3 विकल्पों में से एक के बजाय कभी भी उपयोग नहीं करना चाहिए SELECT max(id) FROM table
, अपने INSERT
स्टेटमेंट द्वारा सिर्फ आईडी जनरेट करने के लिए , क्योंकि (प्रदर्शन के अलावा) यह समवर्ती सुरक्षित नहीं है: आपके INSERT
और आपके SELECT
दूसरे सत्र के बीच एक और रिकॉर्ड सम्मिलित हो सकता है।
SELECT max(id)
दुर्भाग्य से आप जैसे ही पंक्तियों को हटाना शुरू करते हैं, वैसे ही काम नहीं करते हैं।
1,2,3,4,5
और पंक्तियों को हटा दें 4 और 5, अंतिम सम्मिलित आईडी अभी भी 5 है, लेकिन max()
रिटर्न 3.
RETURNING id;
अन्य तालिका में इसे सम्मिलित करने के लिए उपयोग करने का एक नमूना स्वागत योग्य होगा!
RETURNING id
को खिलाए गए एसक्यूएल स्क्रिप्ट के भीतर कैसे उपयोग कर सकता हूं psql
?
INSERT स्टेटमेंट के रीटर्निंग क्लॉज को देखें । असल में, INSERT एक क्वेरी के रूप में दोगुना हो जाता है और आपको वह मान वापस देता है जो डाला गया था।
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
'एड होने के नाते फंक्शन द्वारा लौटा दिया जाता है।
आप निम्नलिखित की तरह, 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
लियोनब्लो का जवाब काफी पूर्ण है। मैं केवल उस विशेष मामले को जोड़ूंगा जिसमें किसी को 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 फ़ंक्शन को तैयार करना चाहते हैं जो क्लाइंट में एक नया रिकॉर्ड सम्मिलित करता है, लेकिन नए व्यक्ति रिकॉर्ड को सम्मिलित करने का भी ध्यान रखता है। उसके लिए, हमें leonbloy के विकल्प 3 की थोड़ी भिन्नता का उपयोग करना चाहिए:
INSERT INTO person(lastname, firstname)
VALUES (lastn, firstn)
RETURNING id INTO [new_variable];
ध्यान दें कि दो INTO क्लॉस हैं। इसलिए, PL / pgSQL फ़ंक्शन को इस तरह परिभाषित किया जाएगा:
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;
अब हम नया डेटा डाल सकते हैं:
SELECT new_client('Smith', 'John');
या
SELECT * FROM new_client('Smith', 'John');
और हमें नवनिर्मित आईडी मिलती है।
new_client
integer
----------
1
नीचे दिए गए उदाहरण देखें
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);
तब अंतिम सम्मिलित आईडी के लिए तालिका "उपयोगकर्ता" seq स्तंभ नाम "id" के लिए इसका उपयोग करें
SELECT currval(pg_get_serial_sequence('users', 'id'));
SELECT CURRVAL(pg_get_serial_sequence('my_tbl_name','id_col_name'))
आपको पाठ्यक्रम का तालिका नाम और स्तंभ नाम की आपूर्ति करने की आवश्यकता है।
यह वर्तमान सत्र / कनेक्शन के लिए होगा । http://www.postgresql.org/docs/8.3/static/functions-fterence.html
इसे इस्तेमाल करे:
select nextval('my_seq_name'); // Returns next value
यदि यह वापसी 1 (या जो भी आपके अनुक्रम के लिए start_value है), तो झूठे ध्वज को पारित करते हुए अनुक्रम को मूल मूल्य पर वापस सेट करें:
select setval('my_seq_name', 1, false);
अन्यथा,
select setval('my_seq_name', nextValue - 1, true);
यह अनुक्रम मान को मूल स्थिति में पुनर्स्थापित करेगा और "सेवल" उस अनुक्रम मान के साथ लौटेगा जिसे आप खोज रहे हैं।
Postgres में एक इनबिल्ट मैकेनिज्म है, जो उसी क्वेरी में id देता है या जो भी आप चाहते हैं वह क्वेरी वापस आ जाती है। यहाँ एक उदाहरण है। विचार करें कि आपके पास एक तालिका बनाई गई है जिसमें 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)
मेरे पास जावा और पोस्टग्रेज के साथ यह मुद्दा था। मैंने इसे एक नए कनेक्टर-जे संस्करण को अपडेट करके तय किया।
PostgreSQL-9.2-1002.jdbc4.jar
https://jdbc.postgresql.org/download.html : संस्करण 42.2.12