PostgreSQL क्वेरी में एक वैरिएबल कैसे घोषित करें


241

मैं PostgreSQL 8.3 क्वेरी में उपयोग के लिए एक चर घोषित कैसे करूं?

MS SQL सर्वर में मैं यह कर सकता हूँ:

DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

मैं PostgreSQL में समान कैसे करूं? प्रलेखन चर के अनुसार बस "नाम प्रकार" के रूप में घोषित किए जाते हैं, लेकिन इससे मुझे एक वाक्यविन्यास त्रुटि मिलती है:

myvar INTEGER;

क्या कोई मुझे सही वाक्यविन्यास का उदाहरण दे सकता है?


2
यह सिर्फ PostgreSQL में किया जा सकता है। इस संबंधित प्रश्न का उत्तर देखें: stackoverflow.com/questions/766657/…
बीन

2
इस संबंधित उत्तर के बेहतर उत्तर हैं: stackoverflow.com/questions/13316773/…
Erwin Brandstetter

जवाबों:


113

PostgreSQL में ऐसी कोई सुविधा नहीं है। आप इसे केवल pl / PgSQL (या अन्य pl / *) में कर सकते हैं, लेकिन सादे SQL में नहीं।

एक अपवाद WITH ()क्वेरी है जो एक चर या चर के रूप में भी काम कर सकता है tuple। यह आपको अस्थायी मूल्यों की एक तालिका वापस करने की अनुमति देता है।

WITH master_user AS (
    SELECT
      login,
      registration_date
    FROM users
    WHERE ...
)

SELECT *
FROM users
WHERE master_login = (SELECT login
                      FROM master_user)
      AND (SELECT registration_date
           FROM master_user) > ...;

मैंने सीटीई की इस पद्धति को चर के रूप में इस्तेमाल करने की कोशिश की। लेकिन जब मैं जल्दी से एक समस्या में भाग गया, जहां सीटीई में अलग-अलग डेटा संशोधन प्रश्नों को एक-दूसरे के प्रभावों को देखने की गारंटी नहीं है। मुझे कई प्रश्नों में उस चर का उपयोग करने के लिए कई सीटीई का उपयोग करना पड़ा।
जिया उल रहमान मुगल

227

मैंने एक WITHक्लॉज का उपयोग करके एक ही लक्ष्य को पूरा किया , यह कहीं भी सुरुचिपूर्ण नहीं है लेकिन एक ही काम कर सकता है। हालांकि इस उदाहरण के लिए यह वास्तव में ओवरकिल है। मैं भी विशेष रूप से यह सिफारिश नहीं है।

WITH myconstants (var1, var2) as (
   values (5, 'foo')
)
SELECT *
FROM somewhere, myconstants
WHERE something = var1
   OR something_else = var2;

2
यह अधिकांश उदाहरणों के लिए बहुत अच्छा काम करता है जहाँ आप चर चाहते हैं। हालाँकि, यदि आप लिमिट (जिसमें चर नहीं हो सकते हैं) के लिए एक चर का उपयोग करना चाहते थे, तो आप \setशाहरियार अहाजानी के उत्तर में सुझाए अनुसार उपयोग करना चाहेंगे ।
साइमन

1
यह मेरे लिए एक आदर्श स्क्रिप्ट है, जहां मैं कुछ रिलेशनल डेटा आयात करना चाहता हूं। जाहिर है मुझे पता नहीं होगा कि अनुक्रम आईडी रिलेशनल डेटा दिया गया है।
रीलेक्चुअल

3
मैंने बस इस दृष्टिकोण की कोशिश की, और शायद एक बेहतर तरीका पाया: JOIN myconstants ON trueऔर फिर उप-चयन करने की कोई आवश्यकता नहीं है।
vektor

7
यह केवल एक ही प्रश्न के भीतर काम करता है, आप WITHएक लेनदेन में CTE को प्रश्नों में साझा नहीं कर सकते हैं ।
डेन्थ

2
पुराना सवाल है, लेकिन यहाँ एक भिन्नता है WITH constants AS (SELECT 5 AS var) SELECT * FROM somewhere CROSS JOIN constants WHERE someting=var;:। CROSS JOIN, एकल-पंक्ति तालिका अभिव्यक्ति के साथ होने के कारण, वास्तविक तालिका में सभी पंक्तियों के लिए डेटा को डुप्लिकेट करता है, और अभिव्यक्ति को सरल करता है।
मन्नजो

82

आप इसे PLPGSQL में भी आज़मा सकते हैं:

DO $$
DECLARE myvar integer;
BEGIN
    SELECT 5 INTO myvar;

    DROP TABLE IF EXISTS tmp_table;
    CREATE TABLE tmp_table AS
    SELECT * FROM yourtable WHERE   id = myvar;
END $$;

SELECT * FROM tmp_table;

उपरोक्त के लिए Postgres 9.0 या बाद के संस्करण की आवश्यकता है।


1
DO स्टेटमेंट PostgreSQL 9.0 में जोड़ा गया था और 8.3 में काम नहीं करता है।
जॉनी

14
रचनात्मक सारणी का उपयोग करें या अस्थायी तालिका का निर्माण करें, न कि सृजन तालिका का उपयोग करें। लेकिन ठीक है।
स्टीफन स्टीगर

60

गतिशील विन्यास सेटिंग्स

आप इसके लिए डायनामिक कॉन्फिग सेटिंग्स का "दुरुपयोग" कर सकते हैं:

-- choose some prefix that is unlikely to be used by postgres
set session my.vars.id = '1';

select *
from person 
where id = current_setting('my.vars.id')::int;

कॉन्फ़िगरेशन सेटिंग्स हमेशा varchar मान हैं, इसलिए आपको उन्हें उपयोग करते समय सही डेटा प्रकार में डालना होगा। यह किसी भी SQL क्लाइंट के साथ काम करता है जबकि \setकेवल में काम करता हैpsql

उपरोक्त के लिए Postgres 9.2 या बाद की आवश्यकता है।

पिछले संस्करणों के लिए, चर को postgresql.confउपयोग किए जाने से पहले घोषित किया जाना था , इसलिए इसने इसकी उपयोगिता को कुछ हद तक सीमित कर दिया। वास्तव में चर पूरी तरह से नहीं, लेकिन विन्यास "वर्ग" जो अनिवार्य रूप से उपसर्ग है। लेकिन एक बार उपसर्ग को परिभाषित करने के बाद, किसी भी चर को बिना बदले इस्तेमाल किया जा सकता हैpostgresql.conf


3
@BrijanElwadhi: हाँ यह लेन-देन है।
a_horse_with_no_name

2
एक साइड नोट के रूप में: कुछ शब्द आरक्षित हैं, उदाहरण के लिए उपज के लिए बदल रहा set session my.vars.id = '1';हैset session my.user.id = '1';ERROR: syntax error at or near "user"
अधिवास

2
@BrijanElwadhi: परिवर्तनीय लेनदेन को विशिष्ट बनाने के लिए आपको इसका उपयोग करना होगा SET LOCAL ...:। sessionचर जब तक आप कनेक्शन है के रूप में प्रभाव में होगा। localलेन-देन के दायरे वाला।
यूजेन कोनकोव

@dominik आप, उद्धरण के साथ कि सीमा के आस-प्राप्त कर सकते हैं जैसे।, कॉल अपेक्षा के अनुरूप काम करता है। set session "my.user.id" = '1';current_setting('my.user.id')
मीलों एल्म

58

यह आपके क्लाइंट पर निर्भर करता है।

हालाँकि, यदि आप psql क्लाइंट का उपयोग कर रहे हैं , तो आप निम्न का उपयोग कर सकते हैं:

my_db=> \set myvar 5
my_db=> SELECT :myvar  + 1 AS my_var_plus_1;
 my_var_plus_1 
---------------
             6

यदि आप पाठ चर का उपयोग कर रहे हैं तो आपको उद्धृत करने की आवश्यकता है।

\set myvar 'sometextvalue'
select * from sometable where name = :'myvar';

1
\setलोअरकेस होना चाहिए
deluan

db = # \ _ profile_id 102 db = #: profile_id; त्रुटि: "102" लाइन 1: 102 पर या उसके पास सिंटैक्स त्रुटि; ^
AlxVallejo

1
@AlxVallejo आपको इसे स्टेटमेंट और psql कंसोल में उपयोग करना होगा । db=> \set someid 8292 db=> SELECT * FROM sometable WHERE id = :someid;
एवरिस

21

Pl / PgSQL के बाहर एक Temp तालिका का उपयोग करना

सुझाव के अनुसार pl / pgsql या अन्य pl / * भाषा का उपयोग करने के बाहर, यह एकमात्र अन्य संभावना है जिसके बारे में मैं सोच सकता था।

begin;
select 5::int as var into temp table myvar;
select *
  from somewhere s, myvar v
 where s.something = v.var;
commit;

13

मैं @ DarioBarrionuevo के जवाब में सुधार का प्रस्ताव करना चाहता हूं , ताकि यह अस्थायी टेम्परिंग को सरल बना सके।

DO $$
    DECLARE myvar integer = 5;
BEGIN
    CREATE TEMP TABLE tmp_table ON COMMIT DROP AS
        -- put here your query with variables:
        SELECT * 
        FROM yourtable
        WHERE id = myvar;
END $$;

SELECT * FROM tmp_table;

डीओ ब्लॉक को हल करने के लिए अच्छा समाधान डेटा सेट वापस नहीं कर सकता है!
कोडफ़ार्मर

PostgreSQL 11.0 पर, इस तरह की क्वेरी रिटर्न 1(संभवतः पंक्ति की गणना) की सामग्री के बजाय tmp_table
एड नूपेल

9

यह समाधान fei0x द्वारा प्रस्तावित एक पर आधारित है, लेकिन इसके फायदे हैं कि क्वेरी में स्थिरांक की मूल्य सूची में शामिल होने की कोई आवश्यकता नहीं है और क्वेरी की शुरुआत में स्थिरांक को आसानी से सूचीबद्ध किया जा सकता है। यह पुनरावर्ती प्रश्नों में भी काम करता है।

मूल रूप से, हर लगातार एक एकल मूल्य तालिका है घोषित खंड के साथ एक में जो तब क्वेरी के शेष भाग में कहीं भी कहा जा सकता है।

  • दो स्थिरांक के साथ मूल उदाहरण:
WITH
    constant_1_str AS (VALUES ('Hello World')),
    constant_2_int AS (VALUES (100))
SELECT *
FROM some_table
WHERE table_column = (table constant_1_str)
LIMIT (table constant_2_int)

वैकल्पिक रूप से आप SELECT * FROM constant_nameइसके बजाय उपयोग कर सकते हैं TABLE constant_nameजो अन्य क्वेरी भाषाओं के लिए अलग नहीं हो सकता है जो कि पोस्टग्रैक्स्ल के लिए अलग है।


6

यहाँ PREPARE कथनों का उपयोग करके एक उदाहरण दिया गया है । आप अभी भी उपयोग नहीं कर सकते हैं ?, लेकिन आप $nनोटेशन का उपयोग कर सकते हैं :

PREPARE foo(integer) AS
    SELECT  *
    FROM    somewhere
    WHERE   something = $1;
EXECUTE foo(5);
DEALLOCATE foo;

काफी अच्छा काम करता है! धन्यवाद।
रुई कार्वाल्हो

4

सच है, एकल-मूल्य चर घोषित करने का कोई ज्वलंत और असंदिग्ध तरीका नहीं है, आप क्या कर सकते हैं

with myVar as (select "any value really")

फिर, इस निर्माण में संग्रहीत मूल्य तक पहुंचने के लिए, आप करते हैं

(select * from myVar)

उदाहरण के लिए

with var as (select 123)    
... where id = (select * from var)

3

आप उपकरण विशेष सुविधाओं का सहारा ले सकते हैं। DBeaver के लिए स्वयं के स्वामित्व सिंटैक्स की तरह:

@set name = 'me'
SELECT :name;
SELECT ${name};

DELETE FROM book b
WHERE b.author_id IN (SELECT a.id FROM author AS a WHERE a.name = :name);

यह प्रयोग करने योग्य है: मैं यह देखने जा रहा हूं कि क्या DBeaver सूचियों और लूपिंग का समर्थन करता है: मुझे एक ही sql को कई स्कीमाओं पर लागू करने की आवश्यकता है और सूची उन्हें लागू करने के लिए स्कीमाओं की होगी।
जवदाबा

1

DBeaver में आप प्रश्नों को मापदंडों का उपयोग कर सकते हैं जैसे आप कोड से कर सकते हैं, इसलिए यह काम करेगा:

SELECT *
FROM somewhere
WHERE something = :myvar

जब आप क्वेरी चलाते हैं तो DBeaver आपसे मूल्य मांगेगा: myvar और क्वेरी चलाएँ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.