it-swarm.com.de

PostgreSQL: Sub-Select im Insert

Ich habe eine Tabelle namens map_tags:

map_id | map_license | map_desc

Und eine weitere Tabelle (widgets), deren Datensätze eine Fremdschlüsselreferenz (1 bis 1) auf einen map_tags-Datensatz enthält:

widget_id | map_id | widget_name

Angesichts der Einschränkung, dass alle map_licenses eindeutig sind (jedoch nicht als Schlüssel für map_tags eingerichtet sind), möchte ich, wenn ich einen map_license und einen widget_name habe, eine Einfügung für widgets ausführen, die sich alle in derselben SQL-Anweisung befindet:

INSERT INTO
    widgets w
(
    map_id,
    widget_name
)
VALUES (
    (
        SELECT
            mt.map_id
        FROM
            map_tags mt
        WHERE
            // This should work and return a single record because map_license is unique
            mt.map_license = '12345'
    ),
    'Bupo'
)

Ich glaube Ich bin auf dem richtigen Weg, weiß aber auf Anhieb, dass dies eine falsche SQL für Postgres ist. Kennt jemand den richtigen Weg, um eine solche Abfrage zu erreichen?

20
Bantha Fodder
INSERT INTO widgets
(
    map_id,
    widget_name
)
SELECT
    mt.map_id, 'Bupo'
FROM
    map_tags mt
WHERE
    mt.map_license = '12345'
23
Clodoaldo Neto

Verwenden Sie die INSERT INTO SELECT-Variante, einschließlich aller Konstanten in der SELECT-Anweisung.

Die PostgreSQL-Syntax INSERT lautet:

INSERT INTO table [ ( column [, ...] ) ]
 { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
 [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

Beachten Sie die Option query am Ende der zweiten Zeile oben.

Hier ist ein Beispiel für Sie.

INSERT INTO 
    widgets
    (
        map_id,
        widget_name
    )
SELECT 
   mt.map_id,
   'Bupo'
FROM
    map_tags mt
WHERE
    mt.map_license = '12345'
30
gahooa

Schnelle Antwort: Sie haben nicht " einen einzelnen Datensatz " Sie haben einen " Satz mit 1 Datensatz " Wenn dies Javascript wäre: Sie haben ein "Array mit 1 Wert" und nicht "1 Wert".

In Ihrem Beispiel wird möglicherweise ein Datensatz in der Unterabfrage Zurückgegeben. Sie versuchen jedoch immer noch, ein "Array" von Datensätzen in separaten Aktualparametern in a zu entpacken Platz, der nur 1 Parameter benötigt.

Ich habe ein paar Stunden gebraucht, um den Kopf um das "Warum nicht" zu wickeln. Da ich versuchte, etwas sehr ähnliches zu tun:

Hier sind meine Notizen:

tb_table01: (no records)
+---+---+---+
| a | b | c | << column names
+---+---+---+

tb_table02:
+---+---+---+
| a | b | c | << column names
+---+---+---+
|'d'|'d'|'d'| << record #1
+---+---+---+
|'e'|'e'|'e'| << record #2
+---+---+---+
|'f'|'f'|'f'| << record #3
+---+---+---+

--This statement will fail:
INSERT into tb_table01
    ( a, b, c )
VALUES
    (  'record_1.a', 'record_1.b', 'record_1.c' ),
    (  'record_2.a', 'record_2.b', 'record_2.c' ),

    -- This sub query has multiple
    -- rows returned. And they are NOT
    -- automatically unpacked like in 
    -- javascript were you can send an
    -- array to a variadic function.
    (
        SELECT a,b,c from tb_table02
    ) 
    ;

nicht denke an "VALUES ​​" als eine variadic - Funktion, die ein Array von Datensätzen entpacken kann. Es gibt kein Argument, das hier entpackt wird, wie Sie es bei einer JavaScript-Funktion Hätten. Sowie:

function takeValues( ...values ){ 
    values.forEach((v)=>{ console.log( v ) });
};

var records = [ [1,2,3],[4,5,6],[7,8,9] ];
takeValues( records );

//:RESULT:
//: console.log #1 : [1,2,3]
//: console.log #2 : [4,5,7]
//: console.log #3 : [7,8,9]

Zurück zu Ihrer SQL-Frage:

Die Realität dieser nicht vorhandenen Funktionalität ändert sich nicht , Nur weil Ihre Unterauswahl nur ein Ergebnis enthält. Es ist Ein " Satz mit einem Datensatz " nicht " ein einzelner Datensatz ".

0
J.M.I. MADISON