2016-04-08 8 views
0

In t-sql ist es möglich, mehrere select-Anweisungen ohne ; auszuführen. Beispiel: select 1 select 2 ist gültig und gibt zwei Datensätze von 1 bzw. 2 zurück.Mehrere Postgres-SQL-Anweisungen in einem einzigen PGexec-Aufruf übergeben

In postgres ist es nicht möglich, mehrere select Anweisungen auszuführen ... Sie benötigen einen ; Begrenzer andernfalls erhalten Sie einen Syntaxfehler.

Referenzierung die Dokumentation: http://www.postgresql.org/docs/current/interactive/libpq-exec.html

Mehrere Abfragen in einem einzigen PQexec Anruf in einer einzigen Transaktion verarbeitet gesendet, es sei denn, es explizit sind BEGIN/COMMIT-Befehle in die Query-String enthalten sie in mehrere Transaktionen aufteilen.

Wie kann ich das tun?

Lassen Sie uns sagen, dass ich diese beiden Abfragen auf dem Server ausgeführt werden soll: select 1 select 2: sollte es so aussehen:

begin select 1 commit; begin select 2 commit

Ich bin ok mit ihm nur die letzte Abfrage als Ergebnismenge, aber ich muss wissen, dass die erste Abfrage auf dem Server ausgeführt wurde, auch wenn sie nicht mit dieser Ergebnismenge zurückkommt.

Warum möchte ich das tun: Ich habe ein komplexes SQL-Skript, das ~ 6 temporäre Tabellen zum Erstellen hat, die die Hauptabfrage verwenden wird. Durch das Abgrenzen der temporären Tabellen mit der ;-Syntax kann ich dieses Skript in cron nicht planen, um einen Zeitplan auszuführen. Wenn ich die temporären Tabellen ausführen kann und die Hauptabfrage, um auf sie in demselben PGexec Aufruf zuzugreifen, würde ich sehr sehr glücklich sein.

+0

Vom feinen Handbuch http wäre: //www.postgresql .org/docs/9.5/static/sql-createtable.html 'Temporäre Tabellen werden automatisch am Ende einer Sitzung oder optional am Ende der aktuellen Transaktion gelöscht (siehe ON COMMIT unten)." – wildplasser

+0

"Durch Abgrenzung .. Ich kann nicht gehen Dieses Script in Cron "- Entschuldigung, ich habe Probleme, das zu verstehen. Warum würde Cron von einer SQL-Skriptdatei betroffen sein? –

+0

@RichardHuxton Ich habe ein Skript, das ich mit 'cron' planen möchte, dieses Skript erstellt einige temporäre Tabellen und führt dann Abfragen für diese temporären Tabellen aus. Wenn ich eine '' '- Beendigung benutze, führt das Skript nur die erste Abfrage aus (erste temporäre Tabelle), keine der nachfolgenden temporären Tabellen/resultierenden Abfragen wird ausgeführt –

Antwort

1

ich war in der Lage zu erreichen, was verwenden psql Ich war auf der Suche für CTEs statt für temporäre Tabellen ... eine lange Kette von CTEs (die als temporäre Tabellen fungieren), die in die Hauptabfrage eintauchen.

Ein einfaches Beispiel:

with first as (
    select 1 as col 
), 
second as (
    select 2 as col 
) 
select * from first union all select * from second 

Ein komplexeres Beispiel:

with COGS as (
    select 'Product1' Vertical, 3.0 Credit, 1.00 Debit, 2.75 Blend, 4.30 Amex, 0.25 ACH union 
    select 'Product2', 3.1, 2.2, 2.8, 4.5, 0.25 union 
), 
Allocable_Card_Volume as (
    select MPR.Date, sum(MPR.Card_Volume_Net_USD) Allocable_Card_Volume 
    from mpr_base MPR 
    where MPR.Gateway in ('YapProcessing') and MPR.Vertical not in ('HA-Intl','HA') 
    group by MPR.Date 
), 
COGS_Financials_Base as (
    select '2013-01-31'::DATE Date , 1000 Total_COGS , 200 Homeaway , (select Allocable_Card_Volume from Allocable_Card_Volume where Date in ('2013-01-31')) Allocable_Card_Volume union 
), 
Initial_COGS as (
    select 
     MPR.Date, 
     sum(
     case when MPR.PaymentTypeGroup in ('ACH_Scan','AmEx') then (Txn_Count * COGS.ACH) else 0 end + 
     case when MPR.Vertical not in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') then 
           coalesce(((Credit_Card_Net_USD - Amex_Processing_Net_USD) * COGS.Credit * 0.01),0) + coalesce((Debit_Card_Net_USD * COGS.Debit * 0.01),0) + coalesce((Amex_Processing_Net_USD * COGS.Amex * 0.01),0) + coalesce((case when TPV is null and PaymentTypeGroup in ('Card') then TPV_Billing else 0 end * COGS.Blend * 0.01),0) 
        when MPR.Vertical in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') and FeePaymentType in ('PropertyPaid') then 
           coalesce(COGS_Financials.Homeaway,0) 
           else 0 end 
     ) Initial_COGS 
    from 
     mpr_base MPR 
     left join COGS on COGS.Vertical = MPR.Vertical and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup not in ('Cash') 
     left join COGS_Financials_Base COGS_Financials on MPR.Date = COGS_Financials.Date and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup in ('Card') 
    where MPR.Gateway in ('YapProcessing') and MPR.Vertical not in ('HA-Intl') and MPR.PaymentTypeGroup not in ('Cash') 
    group by 
     MPR.Date 
), 
COGS_Financials as (
    select 
     COGS_Financials_Base.*, (COGS_Financials_Base.Total_COGS - Initial_COGS.Initial_COGS) Allocation 
    from 
     COGS_Financials_Base 
     join Initial_COGS on COGS_Financials_Base.Date = Initial_COGS.Date 
), 
MPR as (
    select 
     MPR.Date,MPR.Gateway,MPR.Vertical, MPR.ParentAccountId, MPR.ParentName , 
     MPR.PaymentTypeGroup , 
     sum(TPV_USD) TPV_USD, 
     sum(TPV_Net_USD) TPV_Net_USD, 
     sum(Revenue_Net_USD) Revenue_Net_USD , 
     sum(coalesce(
      case when MPR.PaymentTypeGroup in ('ACH_Scan','AmEx') then (Txn_Count * COGS.ACH) else 0 end + 
      case when MPR.Vertical not in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') then 
        coalesce(((Credit_Card_Net_USD - Amex_Processing_Net_USD) * COGS.Credit * 0.01),0) + coalesce((Debit_Card_Net_USD * COGS.Debit * 0.01),0) + coalesce((Amex_Processing_Net_USD * COGS.Amex * 0.01),0) + coalesce((case when TPV is null and PaymentTypeGroup in ('Card') then TPV_Billing else 0 end * COGS.Blend * 0.01),0) 
       +(coalesce(((cast(Card_Volume_Net_USD as decimal(18,2))/cast(COGS_Financials.Allocable_Card_Volume as decimal(18,2))) * COGS_Financials.Allocation ), 0)) -- Excess 
         when MPR.Vertical in ('HA') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') and MPR.FeePaymentType in ('PropertyPaid') then coalesce(COGS_Financials.Homeaway,0) 
         else 0 
      end,0) 
     ) COGS_USD, 
     sum(Txn_Count) Txn_Count 
    from 
     mpr_Base MPR 
     left join COGS on COGS.Vertical = MPR.Vertical and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup not in ('Cash') 
     left join COGS_Financials on MPR.Date = COGS_Financials.Date and MPR.Gateway in ('YapProcessing') and MPR.PaymentTypeGroup in ('Card','AmEx-Processing') 
    where 
     MPR.Date in ('2016-02-29') 
    group by 
     MPR.Date,MPR.Gateway,MPR.Vertical , MPR.ParentAccountId ,MPR.ParentName, 
     MPR.PaymentTypeGroup 
) 
select 
    Vertical, 
    sum(TPV_USD)::money as TPV_USD, 
    sum(Revenue_Net_USD)::money as Revenue_Net_USD, 
    sum(COGS_USD)::money COGS_USD, 
    round((sum(Revenue_Net_USD)-sum(COGS_USD))/sum(Revenue_Net_USD)*100,2) Accounting_Margin 
from 
    MPR 
where Date in ('2016-02-29') 
group by 
    Vertical 
union all 
select 
    'Total' , 
    sum(TPV_USD)::money as TPV_USD, 
    sum(Revenue_Net_USD)::money as Revenue_Net_USD, 
    sum(COGS_USD)::money COGS_USD, 
    round((sum(Revenue_Net_USD)-sum(COGS_USD))/sum(Revenue_Net_USD)*100,2) Accounting_Margin 
from 
    MPR 
where Date in ('2016-02-29') 

sagte ich es komplex :-)

+0

Dies ist nicht komplex. Dies ist ein zu komplexes * Konstrukt *. – wildplasser

0

Sie libpq nicht, können Sie einfach er vorderes Ende (in cron, müssen Sie möglicherweise die absoluten Pfadnamen für die binären)

#!/bin/sh 
psql -U my_user mydb <<OMG 
    begin; 
    select tralal 1; 
    commit; 

    begin; 
    select domtidom 2; 
    commit; 
OMG 
+0

Irgendwie könnte ich nur 100% Embedded SQL dafür verwenden, und nicht das Tool 'psql' verwenden? Verwenden Sie zum Beispiel die Postico GUI (oder pgAdmin III) in einem Abfragefenster, um sowohl 'select 1 select 2' als auch die benötigte Syntax auszugeben, um beide Abfragen auf dem Server auszuführen? (& Ergebnisse aus der ersten Abfrage müssen nicht zurück zum Client gesendet werden) –

+0

Ja, Sie können ein Frontend auf Basis von libpq erstellen. Einfach die Kommentare herausfiltern, das nächste ';' finden und einreichen (Vorsicht vor Strings!) Und die Ergebnisse abrufen und wegwerfen. Das Übergeben von Parametern an vorbereitete Abfragen wird etwas schwieriger. Aber all das ist im Grunde genau das, was 'psql dbname /dev/null' tut. – wildplasser

+0

Und wenn Sie mehrere Anweisungen ** OHNE ** ';' Terminierung zwischen zulassen möchten, benötigen Sie einige minimale Art von Parser (SQL ist nicht LL (1), so wird dies keine schöne Aufgabe sein. Vielleicht ein 3. Ordnung Markov-Filter könnte funktionieren) Viel Glück! – wildplasser

Verwandte Themen