PostgreSQL: Komut satırından parametreler nasıl aktarılır?


95

Yer ?tutucular kullanan bir komut dosyasında biraz ayrıntılı bir sorgum var . Aynı sorguyu doğrudan psql komut satırından (komut dosyasının dışında) test etmek istedim. İçeri girmekten ve tüm ?gerçek değerlerle değiştirmekten kaçınmak istiyorum , bunun yerine argümanları sorgudan sonra iletmek istiyorum.

Misal:

SELECT  * 
FROM    foobar
WHERE   foo = ?
   AND  bar = ?
    OR  baz = ?  ;

Şunun gibi bir şey arıyorum:

%> {select * from foobar where foo=? and bar=? or baz=? , 'foo','bar','baz' };

Daha fazla içerik lütfen. Bu sorgu bir SQL dosyasında mı, Perl / Python / Ruby / <buraya en sevdiğiniz komut dosyası dilini girin> komut dosyasında mı yoksa başka bir yerde mi?

@Jack: Bunu doğrudan psql isteminden (komut satırı) yapmak istiyorum. Kodumu bir komut dosyasından alıyorum, ancak tüm bul / değiştir sürecinden geçmek istemiyorum.
vol7ron

@ Vol7ron, bir psql komut satırı örneği için lütfen aşağıdaki cevabıma bakın.
MAbraham 1

1
@ MAbraham1: güzel. Soruma biraz daha arka plan vermeliydim. Açık metinde SQL olan birçok komut dosyam var. Bazen bunları almak ve bunları hata ayıklama için özel değerlerle doğrudan veritabanına vurmak yararlıdır. Postgres içinde ek dosyaları kaydetmeye gerek kalmadan bunu kolayca yapmanın bir yolunu arıyordum.
vol7ron

@ Vol7ron, teşekkürler. Toplu işler açısından düşünüyordum, ancak belirteçleri açık SQL'de de kullanabilmelisiniz. Cevabımı beğendiyseniz oy vermeyi unutmayın.
MAbraham1

Yanıtlar:


181

Örneğin -v yapısını kullanabilirsiniz.

psql -v v1=12  -v v2="'Hello World'" -v v3="'2010-11-12'"

ve sonra sql'deki değişkenlere şu şekilde bakın: v1,: v2 vb.

select * from table_1 where id = :v1;

Lütfen dize / tarih değerini iki tırnak kullanarak nasıl geçirdiğimize dikkat edin " '...' "


2
+1 İlginç, adlandırılmış argümanlar iletiyor. Giriş yaptıktan sonra bunu yapmanın herhangi bir yolunun farkında mısınız?
vol7ron

9
Tabii, sadece kullan \set v3 'another value'. Unutmayın, SQL ifadesindeki değeri tırnak içine almanız gerektiğinde, değişken adının etrafına kesme işareti SELECT * FROM foo WHERE bar = :'v3';
koyun

2
Sanırım bunu şuradan aldılarawk
Neil McGuigan

1
Yerine

5
Not, bunu okuduktan sonra -v ile ayarlanan değişkenlerin -c ile çalıştırılan komutlar için mevcut olacağını ummuştum, ama ne yazık ki değiller. Başka bir deyişle, psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" -c 'select * from table_1 where id = :v1;' sözdizimi hatası oluşturacaktır. Ancak, bash sizin kabuğunuzsa, deneyebilirsiniz: psql -v v1=12 -v v2="'Hello World'" -v v3="'2010-11-12'" <<< 'select * from table_1 where id = :v1;' iyi bir etki için.
malcook

31

PostgreSQL'de keşfedildi, tıpkı bir betik dilinde yapabildiğiniz gibi PREPAREifadeler kullanabilirsiniz. Ne yazık ki, yine de kullanamazsınız ?, ancak $ngösterimi kullanabilirsiniz .

Yukarıdaki örneği kullanarak:

PREPARE foo(text,text,text) AS
    SELECT  * 
    FROM    foobar
    WHERE   foo = $1
       AND  bar = $2
        OR  baz = $3  ;
EXECUTE foo('foo','bar','baz');
DEALLOCATE foo;

@IvanBlack buna dahil etmek istediğiniz başka bir şey var mıydı? :) serbest
bırakma

Sadece şu anda foomeşgul olduğunu ve PREPAREmevcut oturum kapalı değilken başka bir adın olması gerektiğini unutmayın . Birlikte oynarsanız PREPAREiçine psqlyeni bir isim her seferinde icat etmek zor ve DEALLOCATE) = onunla yardımcı olabilir
Ivan Siyah

Bundan bahsettiğiniz için teşekkürler. Bir süredir PREPARE kullanmadım, ancak bu yararlı bir bilgi
vol7ron

Bu çözüm IMO çok iyi. Yararlı bir yan etki - hazırlanan ifadeyi birçok kez kolayca arayabilirsiniz.
Yuri

14

Psql'de bir mekanizma vardır.

\set name val

komut -v name=valsatırı seçeneğine bağlı olması gereken komut. Alıntı yapmak acı vericidir, çoğu durumda tüm sorgu etini bir kabuk buradaki belgeye koymak daha kolaydır.

Düzenle

oops, demeliydim -vyerine -Pönceki yanıt doğru var (biçimlendirme seçenekleri için olan).


7

Ayrıca parametreleri psql komut satırından veya bir toplu iş dosyasından da iletebilirsiniz. İlk ifadeler, veritabanınıza bağlanmak için gerekli ayrıntıları toplar.

Son istem, WHERE column IN () yan tümcesinde kullanılacak kısıtlama değerlerini sorar. Dizeleri tek tırnak içine almayı ve virgülle ayırmayı unutmayın:

@echo off
echo "Test for Passing Params to PGSQL"
SET server=localhost
SET /P server="Server [%server%]: "

SET database=amedatamodel
SET /P database="Database [%database%]: "

SET port=5432
SET /P port="Port [%port%]: "

SET username=postgres
SET /P username="Username [%username%]: "

SET /P bunos="Enter multiple constraint values for IN clause [%constraints%]: "
ECHO you typed %constraints%
PAUSE
REM pause
"C:\Program Files\PostgreSQL\9.0\bin\psql.exe" -h %server% -U %username% -d %database% -p %port% -e -v v1=%constraints% -f test.sql

Şimdi SQL kod dosyanızda, v1 belirtecini WHERE yan tümcenizin içine veya SQL'de başka herhangi bir yere ekleyin. Belirteçlerin yalnızca bir dosyada değil, açık bir SQL ifadesinde de kullanılabileceğini unutmayın. Bunu test.sql olarak kaydedin:

SELECT * FROM myTable
WHERE NOT someColumn IN (:v1);

Windows'ta tüm dosyayı DOS BATch dosyası (.bat) olarak kaydedin, test.sql'yi aynı dizine kaydedin ve toplu iş dosyasını başlatın.

EnterpriseDB'den Dave Page için orijinal komut dosyası için teşekkür ederiz.


Windows örneği için +1; çoğu Pg veritabanı * nix varyantında mevcut olsa da
vol7ron

2

Görünüşe göre, istediğiniz şey doğrudan komut satırından yapılamaz . Ya plpgsql'de kullanıcı tanımlı bir işlev kullanmanız ya da sorguyu bir komut dosyası dilinden çağırmanız gerekir (ve ikinci yaklaşım SQL enjeksiyonundan kaçınmayı biraz daha kolaylaştırır).


Ben değildim - çoğu kez, isimsiz bırakılsa bile, olumsuz oyların bir tür açıklama gerektirmesini (soruları kapatmak için neden oy kullandığımız gibi) gerektirmesini isterdim.
vol7ron

0

@ Malcook'un yorumundan esinlenerek (bash kullanarak) başka bir cevap sunmak istiyorum.

Bayrağı kullanırken sorgunuzda kabuk değişkenleri kullanmanız-c gerekiyorsa bu seçenek işinize yarayabilir . Özellikle, adı bir kabuk değişkeni olan (kullanırken doğrudan geçemeyeceğiniz -c) bir tablonun sayısını almak istedim .

Kabuk değişkeninize sahip olduğunuzu varsayın

$TABLE_NAME='users'

Daha sonra bunun sonuçlarını kullanarak

psql -q -A -t -d databasename -c <<< echo "select count(*) from $TABLE_NAME;"

( -q -A -tsadece elde edilen numarayı ek biçimlendirme olmadan yazdırmak içindir)

Ben dikkat edecek echoBurada-string (içinde <<<operatör) gerekli olmayabilir, ben aslen kendileri tarafından tırnak belki birisi bu nedenini şöyle açıklamak mümkündür, ince olacağını düşündüm.


0

@ Vol7ron yanıtının daha iyi bir sürümünü kullandım:

DO $$
BEGIN
    IF NOT EXISTS(SELECT 1 FROM pg_prepared_statements WHERE name = 'foo') THEN
        PREPARE foo(text,text,text) AS
            SELECT  * 
            FROM    foobar
            WHERE   foo = $1
                AND bar = $2
                OR  baz = $3;
    END IF;
END$$;
EXECUTE foo('foo','bar','baz');

Bu şekilde her zaman bu sırayla çalıştırabilir (sorgu sadece henüz hazırlanmamışsa hazırlanır), yürütmeyi tekrarlayabilir ve son sorgudan sonucu alabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.