সর্বশেষ sertedোকানো আইডি পেতে পোস্টগ্রিএসকিউএল-তে কার্ভাল () কীভাবে ব্যবহার করব?


64

আমার একটি টেবিল রয়েছে:

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

Tableোকানো ব্যবহার না করেই আমি সেই টেবিল থেকে "সর্বশেষ inোকানো আইডি" চাই RETURNING id। একটি ফাংশন বলে মনে হচ্ছে CURRVAL()তবে এটি কীভাবে ব্যবহার করতে হয় তা আমি বুঝতে পারি না।

আমি চেষ্টা করেছি:

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

কিন্তু তাদের কেউ কাজ করে না। আমি currval()সর্বশেষ sertedোকানো আইডি পেতে কীভাবে ব্যবহার করতে পারি ?


2
এই সমস্যা / সমাধানের পাঠকদের সচেতন হওয়া উচিত যে কার্নাল () এর ব্যবহারকে সাধারণত নিরুৎসাহিত করা হয় কারণ রিটার্নিং ক্লজটি অতিরিক্ত ক্যোয়ারের ওভারহেড ব্যতীত এবং WRONG VALUE (যা কার্ভালটি করবে তা কার্যকর করবে) ছাড়াই সনাক্তকারীকে সরবরাহ করে কিছু ব্যবহারের ক্ষেত্রে।)
15:58

1
@ চন্দর: এই দাবির জন্য আপনার কি কোনও রেফারেন্স আছে? এর ব্যবহার currval() অবশ্যই নিরুৎসাহিত নয়।
a_horse_with_no_name

সম্ভবত এটি কার্ভাল ব্যবহারকে নিরুৎসাহিত করা হয়েছে কিনা সে সম্পর্কে মতামতের বিষয়, তবে কিছু ক্ষেত্রে ব্যবহারকারীদের সচেতন হওয়া উচিত যে এটি এমন কোনও মূল্য সরবরাহ করতে পারে যা আপনি প্রত্যাশা করেন না (এইভাবে সমর্থিত যেখানে আরও ভাল পছন্দটি প্রত্যাবর্তন করা হয়েছে।) মনে করুন আপনি একটি সারণী A রয়েছে যা ক্রম a_seq ব্যবহার করে, এবং টেবিল বি যা পিকে কলামের জন্য a_seq (পরের ((a_seq) কলিং) ব্যবহার করে uses) ব্যবহার করে have সেক্ষেত্রে কার্লভাল () ফাংশন (টেবিল এ সন্নিবেশের পরে) টেবিল বি তে সন্নিবেশ করানোর জন্য উত্পন্ন নম্বরটি ফিরিয়ে দেবে, টেবিল এ নয়
চাঁদর

উত্তর:


51

আপনি যদি serialPostgreSQL হিসাবে একটি কলাম তৈরি করেন তবে স্বয়ংক্রিয়ভাবে সেটির জন্য একটি ক্রম তৈরি হয়।

সিকোয়েন্সটির নামটি স্বয়ংক্রিয়ভাবে তৈরি হয় এবং সর্বদা টেবিলের নাম_কলামনাম_সেক হয়, আপনার ক্ষেত্রে ক্রমটির নাম হবে 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'));

এইভাবে আপনার পোস্টগ্রিসের নামকরণের কৌশলটি নির্ভর করে না।

বা আপনি যদি সিকোয়েন্সের নামটি মোটেও ব্যবহার করতে না চান তবে ব্যবহার করুন lastval()


আমি অনুমান করি যে currval()কোনও মাল্টি-ইউজার সেটআপে এটি ব্যবহার করা ভাল নয় । যেমন একটি ওয়েব সার্ভারে।
জোনাস

9
না আপনি ভুল করছেন currval()আপনার বর্তমান সংযোগে "স্থানীয়"। সুতরাং এটি কোনও বহু ব্যবহারকারীর পরিবেশে ব্যবহার করতে কোনও সমস্যা নেই is এটি একটি ক্রমের পুরো উদ্দেশ্য।
a_horse_with_no_name

1
এটি (বেশ বিরল) ক্ষেত্রে ভঙ্গ হতে পারে যেখানে আপনার সন্নিবেশ একই টেবিলে আরও সন্নিবেশ সঞ্চারিত করে, না?
লিওনব্লয়

1
@ এ_হর্স_বিহীন_নাম_নাম: আমি একাধিক সন্নিবেশগুলিতে (এটি স্পষ্ট করা সহজ) না হয়ে টেবিলে সংজ্ঞায়িত (সম্ভবত অজানা) ট্রিগারগুলি নিয়ে ভাবছিলাম। উপরোক্ত উদাহরণগুলির
লিওনব্লায়

1
এটি সর্বদা টেবিল এবং কলামের নাম নয়। যদি ইতিমধ্যে সেই নামের সাথে কোনও সিকোয়েন্স থাকে তবে এটি শেষে একটি সংখ্যাকে সংক্ষিপ্ত করে বা বাড়িয়ে নতুন ক্রম তৈরি করবে এবং এটি সীমা ছাড়িয়ে গেলে নামটি ছোট করার প্রয়োজন হতে পারে (যা 62 টি অক্ষরের বলে মনে হচ্ছে)।
ফিলিচ হিবস

47

এটি স্ট্যাক ওভারফ্লো থেকে সরাসরি

এটি যেমন @a_horse_with_no_name এবং @ জ্যাক ডগলাস দ্বারা চিহ্নিত করা হয়েছিল, কার্লভাল কেবলমাত্র বর্তমান অধিবেশন দিয়ে কাজ করে। সুতরাং আপনি যদি এই সত্যটির সাথে ঠিক থাকেন যে ফলাফলটি অন্য সেশনের অনির্ধারিত লেনদেনের ফলে প্রভাবিত হতে পারে এবং আপনি এখনও এমন কিছু চান যা অধিবেশন জুড়ে কাজ করবে, আপনি এটি ব্যবহার করতে পারেন:

SELECT last_value FROM your_sequence_name;

আরও তথ্যের জন্য এসও এর লিঙ্কটি ব্যবহার করুন।

পোস্টগ্রিস ডকুমেন্টেশন থেকে যদিও এটি স্পষ্টভাবে বলা আছে

যদি পরবর্তী অধিবেশনটি বর্তমান অধিবেশনটিতে এখনও না বলা হয় তবে শেষেরটিকে কল করা একটি ত্রুটি।

সুতরাং আমি অনুমান করি যে সেশনজুড়ে ক্রমের জন্য কার্ভাল বা লাস্ট_ভ্যালু সঠিকভাবে ব্যবহার করার জন্য, আপনার মতো কিছু করা দরকার?

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

অবশ্যই ধরে নিই যে আপনার বর্তমান সেশনে সিরিয়াল ক্ষেত্রটি ব্যবহারের কোনও সন্নিবেশ বা অন্য কোনও উপায় থাকবে না।


3
আমি কখনই এমন পরিস্থিতিটি ভাবতে পারি না যখন এটি কার্যকর হবে।
ypercubeᵀᴹ

আমি কেবল ভাবছিলাম যে এটি কার্ভাল পাওয়ার কোনও উপায়, যদি পরবর্তী অধিবেশনটি বর্তমান অধিবেশনটিতে না ডাকা হয়। তাহলে কোন পরামর্শ?
স্ল্যাক

আমি যখন জেনারেটেড ফিক্সিং ডেটার জন্য প্রাথমিক কীগুলি হার্ড-কোডিং করছিলাম তখন আমি এটি করতে হয়েছিল যেখানে আমি পিকে মানগুলি চেয়েছিলাম যা ক্লায়েন্টের পরীক্ষা সহজতর করার জন্য সময়ের পূর্বে বর্ধিতভাবে উত্পন্ন হবে। সাধারণত কোনও ডিফল্ট মান দ্বারা নিয়ন্ত্রিত কলামে এটি করার সময় সন্নিবেশগুলিকে সমর্থন করার জন্য nextval()আপনাকে তারপরে হার্ডকডযুক্ত আইডি সহ সন্নিবেশকৃত ফিক্সচার রেকর্ডের সাথে ম্যানুয়ালি ক্রম নির্ধারণ করতে হবে। এছাড়াও, কার্ভাল () / শেষের () প্রাক-নেক্সটালটি উপলভ্য না হওয়ার সমস্যার সমাধানের উপায়টি কেবল SELECTসিকোয়েন্সে সরাসরি।
পিটার এম এলিয়াস

@ ypercubeᵀᴹ বিপরীতে, আমি বেছে নেওয়া "সঠিক" উত্তরটি ব্যবহার করার কোনও ভাল কারণ নিয়ে ভাবতে পারি না। এই উত্তরের সারণীতে একটি রেকর্ড সন্নিবেশ করা প্রয়োজন হয় না। এটি প্রশ্নেরও উত্তর দেয়। আবার, আমি এই উত্তরটি বেছে নেওয়া কোনওটির জন্য না ব্যবহার করার কোনও ভাল কারণ নিয়ে ভাবতে পারি।
হেনলি চিউ

1
এই উত্তরে টেবিলটি মোটেও জড়িত নয়। চেক করা হয়। আদর্শভাবে, আপনি মোটেও কোনও পরিবর্তন না করে শেষ আইডিটি জানতে চান। এটি যদি প্রোডাকশন ডিবি হয়? আপনি সম্ভাব্য পার্কশন ছাড়া কেবল একটি এলোমেলো সারি inোকাতে পারবেন না। সুতরাং এই উত্তর নিরাপদ পাশাপাশি সঠিক।
হেনলি চিউ

14

আপনার আগে এই সেশনে এই ক্রমটির জন্য কল করতে হবেnextvalcurrval :

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)

3

সুতরাং এই বিভিন্ন পদ্ধতিতে কিছু সমস্যা রয়েছে:

কার্ভালটি কেবলমাত্র বর্তমান সেশনে উত্পন্ন সর্বশেষ মানটি অর্জন করে - এটির দুর্দান্ত যা যদি আপনার কাছে আর কোনও উত্পন্ন মান না থাকে তবে আপনি যদি ট্রিগার কল করতে পারেন এবং / অথবা বর্তমান লেনদেনে এটির ক্রমটি একাধিকবার উন্নত হয়েছে সঠিক মান ফিরে যাচ্ছে না। এটি সেখানে 99% জনগণের জন্য কোনও সমস্যা নয় - তবে এটি এমন একটি বিষয় যা বিবেচনা করা উচিত।

Sertোকানো অপারেশনের পরে অনন্য শনাক্তকারীকে নিয়োগের সর্বোত্তম উপায় হ'ল রিটার্নিং ক্লজটি। নীচের উদাহরণটি ধরে নেওয়া হয়েছে যে অনুক্রমের সাথে আবদ্ধ কলামটিকে "আইডি" বলা হয়:

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

মনে রাখবেন যে প্রত্যাবর্তনের ধারাটির উপযোগিতা কেবল সিক্যুয়েন্স পাওয়ার বাইরে চলেছে, যেহেতু এটিও হবে:

  • রিটার্ন মানগুলি যা "চূড়ান্ত সন্নিবেশ" এর জন্য ব্যবহৃত হয়েছিল (উদাহরণস্বরূপ, আগে কোনও ট্রিগার তথ্য সন্নিবেশ করানোতে পরিবর্তন করতে পারে))
  • মুছে ফেলা হচ্ছে যে মানগুলি ফেরত দিন:

    আইডি> 100 ফিরে * যেখানে টেবিল এ থেকে মুছুন

  • একটি আপডেটের পরে পরিবর্তিত সারিগুলি ফিরিয়ে দিন:

    আপডেট টেবিল একটি সেট এক্স = 'y' যেখানে ব্লাহ = 'ব্লিচ' ফিরে *

  • একটি আপডেটের জন্য মুছার ফলাফল ব্যবহার করুন:

    এ হিসাবে (টেবিল এ থেকে রিটার্নিং আইডি হিসাবে * মুছুন) আপডেট বি সেট মুছে ফেলা = যেখানে আইডি ইন (এ থেকে আইডি নির্বাচন করুন);


অবশ্যই, ওপি স্পষ্টভাবে বলেছিল যে তারা একটি RETURNINGধারা ব্যবহার করতে চায় না - তবে, এটি অন্যদের কাছে পরিষ্কারভাবে ব্যবহারের সুবিধাগুলি তৈরি করার ক্ষেত্রে কোনও ভুল নেই।
আরডিফোজ 4'17

আমি সত্যিই কেবলমাত্র অন্যান্য বিভিন্ন পদ্ধতির অসুবিধাগুলি তুলে ধরার চেষ্টা করছিলাম (এটির ক্ষেত্রে যদি কেউ সতর্ক না হন তবে এটি প্রত্যাশিত মান ব্যতীত অন্য কোনও মান ফেরত দিতে পারে) - এবং সর্বোত্তম অনুশীলনটি স্পষ্ট করে বলুন।
চাঁদ

1

এসকিউএএলএলচেমি ব্যবহার করেও আমাকে একটি ক্যোয়ারী চালাতে হয়েছিল কারণ আমি কার্ভাল ব্যবহারে সফল হইনি।

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

এটি একটি পাইথন ফ্লাস্ক + পোস্টগ্র্যাস্কিল প্রকল্প ছিল।


1

যদি আপনি কল না করে এবং সিকোয়েন্সটি nextval()পরিবর্তন না করেই সিকোয়েন্সগুলির মান পেতে চান তবে আমি এটি পরিচালনা করতে একটি পিএল / পিজিএসকিউএল ফাংশন একসাথে ছুঁড়ে ফেলেছি: সমস্ত ডাটাবেস সিকোয়েন্সের মানটি সন্ধান করুন


1

আপনার এর GRANTমতো স্কিমা ব্যবহার করতে হবে:

GRANT USAGE ON SCHEMA schema_name to user;

এবং

GRANT ALL PRIVILEGES ON schema_name.sequence_name TO user;

1
Dba.se স্বাগতম! আপনার প্রথম পোস্টে চিয়ার্স! দেখে মনে হচ্ছে না যে মূল পোস্টটি বিশেষত অনুমতি সম্পর্কিত regarding currval()ফাংশনটিকে এই থ্রেডটির সাথে কিছুটা আরও প্রাসঙ্গিক করার জন্য কল করার সময় অনুমতি ব্যর্থতার আশেপাশে কিছু নির্দিষ্টকরণ অন্তর্ভুক্ত করার জন্য আপনার উত্তরকে প্রসারিত করার কথা বিবেচনা করুন ?
পিটার ভ্যান্ডিভিয়ার

0

PostgreSQL 11.2 এ আপনি ক্রমটিকে টেবিলের মতো আচরণ করতে পারেন বলে মনে হচ্ছে:

উদাহরণস্বরূপ যদি আপনার নাম অনুসারে একটি ক্রম থাকে: 'নাম_ইড_সেক'

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

এটি আপনাকে সর্বশেষ sertedোকানো আইডি দেবে (এই ক্ষেত্রে 4) যার অর্থ বর্তমান মান (বা পরবর্তী আইডির জন্য ব্যবহার করা উচিত এমন মান) 5 হওয়া উচিত।


-2

বর্তমান বা পরের সিকোয়েন্স আইডি পেতে পোস্টগ্রেএসকিউএল এর বিভিন্ন সংস্করণে বিভিন্ন ফাংশন থাকতে পারে।

প্রথমত, আপনাকে আপনার পোস্টগ্রিজের সংস্করণটি জানতে হবে। নির্বাচন করা সংস্করণ () ব্যবহার করে; সংস্করণ পেতে।

PostgreSQL 8.2.15 এ আপনি ব্যবহার করে বর্তমান সিকোয়েন্স আইডি পাবেন select last_value from schemaName.sequence_name

উপরের বিবৃতিটি যদি কাজ না করে তবে আপনি ব্যবহার করতে পারেন select currval('schemaName.sequence_name');


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