it-swarm.com.de

SQL select join: Können alle Spalten als Präfix * vorangestellt werden?

Ich frage mich, ob dies in SQL möglich ist. Angenommen, Sie haben zwei Tabellen A und B, und Sie wählen Tabelle A aus und verbinden Tabelle B:

SELECT a.*, b.* FROM TABLE_A a JOIN TABLE_B b USING (some_id);

Wenn Tabelle A die Spalten 'a_id', 'name' und 'some_id' enthält und Tabelle B 'b_id', 'name' und 'some_id', gibt die Abfrage die Spalten 'a_id', 'name', 'some_id zurück ',' b_id ',' name ',' some_id '. Gibt es eine Möglichkeit, den Spaltennamen der Tabelle B voranzustellen, ohne jede Spalte einzeln aufzulisten? Das Äquivalent davon:

SELECT a.*, b.b_id as 'b.b_id', b.name as 'b.name', b.some_id as 'b.some_id'
FROM TABLE_A a JOIN TABLE_B b USING (some_id);

Aber wie gesagt, ohne jede Spalte aufzulisten, so etwas wie:

SELECT a.*, b.* as 'b.*'
FROM TABLE_A a JOIN TABLE_B b USING (some_id);

Grundsätzlich etwas zu sagen "vor jeder Spalte, die von b. * Zurückgegeben wird," etwas "." Ist das möglich oder habe ich kein Glück?

Vielen Dank im Voraus für Ihre Hilfe!

BEARBEITEN: Ratschläge zur Nichtbenutzung von SELECT * usw. sind zwar gültige Ratschläge, aber in meinem Kontext nicht relevant. Halten Sie sich also an das vorliegende Problem. Ist es möglich, ein Präfix (eine in der SQL-Abfrage festgelegte Konstante) zu allen zu verwenden? Spaltennamen einer Tabelle in einem Join?

BEARBEITEN: Mein oberstes Ziel ist es, ein SELECT * für zwei Tabellen mit einem Join ausführen zu können und anhand der Namen der Spalten, die ich in meiner Ergebnismenge bekomme, herauszufinden, welche Spalten aus Tabelle A stammen und welche Spalten aus Tabelle B. Auch hier möchte ich keine Spalten einzeln auflisten, ich muss ein SELECT * ausführen können.

172
foxdonut

Ich sehe hier zwei mögliche Situationen. Zunächst möchten Sie wissen, ob es dafür einen SQL-Standard gibt, den Sie generell unabhängig von der Datenbank verwenden können. Nein, da ist kein. Zweitens möchten Sie wissen, was ein bestimmtes dbms-Produkt betrifft. Dann müssen Sie es identifizieren. Ich denke jedoch, dass die wahrscheinlichste Antwort ist, dass Sie etwas wie "a.id, b.id" zurückbekommen, da Sie auf diese Weise die Spalten in Ihrem SQL-Ausdruck identifizieren müssen. Der einfachste Weg, die Standardeinstellung herauszufinden, besteht darin, eine solche Abfrage zu senden und zu sehen, was Sie zurückbekommen. Wenn Sie angeben möchten, welches Präfix vor dem Punkt steht, können Sie beispielsweise "SELECT * FROM a AS my_alias" verwenden.

34
dkretz

Anscheinend lautet die Antwort auf Ihre Frage nein. Allerdings können Sie einen Hack verwenden, indem Sie jeder neuen Tabelle eine Dummy-Spalte zuweisen. Dies funktioniert besonders gut, wenn Sie eine Ergebnismenge für eine Liste von Spalten in einer Skriptsprache wie Python oder PHP durchlaufen.

SELECT '' as table1_dummy, table1.*, '' as table2_dummy, table2.*, '' as table3_dummy, table3.* FROM table1
JOIN table2 ON table2.table1id = table1.id
JOIN table3 ON table3.table1id = table1.id

Ich weiß, dass dies Ihre Frage nicht genau beantwortet, aber wenn Sie ein Kodierer sind, können Sie Tabellen mit doppelten Spaltennamen voneinander trennen. Hoffe das hilft jemandem.

57
Wayne Bryan

Ich verstehe vollkommen, warum dies notwendig ist - zumindest für mich ist es beim Rapid Prototyping praktisch, wenn viele Tabellen zusammengefügt werden müssen, einschließlich vieler Inner Joins. Sobald ein Spaltenname in einem zweiten Platzhalterfeld "jointable. *" Gleich ist, werden die Feldwerte der Haupttabelle mit den Werten der jointable überschrieben. Fehleranfällig, frustrierend und eine Verletzung von DRY, wenn die Tabellenfelder immer wieder manuell mit Aliasnamen angegeben werden müssen ...

Hier ist eine PHP (Wordpress) -Funktion, um dies durch die Codegenerierung zusammen mit einem Beispiel für deren Verwendung zu erreichen. Im Beispiel wird es verwendet, um schnell eine benutzerdefinierte Abfrage zu generieren, die die Felder eines zugehörigen Wordpress-Posts bereitstellt, auf den über ein advanced custom fields - Feld verwiesen wurde.

function prefixed_table_fields_wildcard($table, $alias)
{
    global $wpdb;
    $columns = $wpdb->get_results("SHOW COLUMNS FROM $table", ARRAY_A);

    $field_names = array();
    foreach ($columns as $column)
    {
        $field_names[] = $column["Field"];
    }
    $prefixed = array();
    foreach ($field_names as $field_name)
    {
        $prefixed[] = "`{$alias}`.`{$field_name}` AS `{$alias}.{$field_name}`";
    }

    return implode(", ", $prefixed);
}

function test_prefixed_table_fields_wildcard()
{
    global $wpdb;

    $query = "
    SELECT
        " . prefixed_table_fields_wildcard($wpdb->posts, 'campaigns') . ",
        " . prefixed_table_fields_wildcard($wpdb->posts, 'venues') . "
        FROM $wpdb->posts AS campaigns
    LEFT JOIN $wpdb->postmeta meta1 ON (meta1.meta_key = 'venue' AND campaigns.ID = meta1.post_id)
    LEFT JOIN $wpdb->posts venues ON (venues.post_status = 'publish' AND venues.post_type = 'venue' AND venues.ID = meta1.meta_value)
    WHERE 1
    AND campaigns.post_status = 'publish'
    AND campaigns.post_type = 'campaign'
    LIMIT 1
    ";

    echo "<pre>$query</pre>";

    $posts = $wpdb->get_results($query, OBJECT);

    echo "<pre>";
    print_r($posts);
    echo "</pre>";
}

Die Ausgabe:

SELECT
    `campaigns`.`ID` AS `campaigns.ID`, `campaigns`.`post_author` AS `campaigns.post_author`, `campaigns`.`post_date` AS `campaigns.post_date`, `campaigns`.`post_date_gmt` AS `campaigns.post_date_gmt`, `campaigns`.`post_content` AS `campaigns.post_content`, `campaigns`.`post_title` AS `campaigns.post_title`, `campaigns`.`post_excerpt` AS `campaigns.post_excerpt`, `campaigns`.`post_status` AS `campaigns.post_status`, `campaigns`.`comment_status` AS `campaigns.comment_status`, `campaigns`.`ping_status` AS `campaigns.ping_status`, `campaigns`.`post_password` AS `campaigns.post_password`, `campaigns`.`post_name` AS `campaigns.post_name`, `campaigns`.`to_ping` AS `campaigns.to_ping`, `campaigns`.`pinged` AS `campaigns.pinged`, `campaigns`.`post_modified` AS `campaigns.post_modified`, `campaigns`.`post_modified_gmt` AS `campaigns.post_modified_gmt`, `campaigns`.`post_content_filtered` AS `campaigns.post_content_filtered`, `campaigns`.`post_parent` AS `campaigns.post_parent`, `campaigns`.`guid` AS `campaigns.guid`, `campaigns`.`menu_order` AS `campaigns.menu_order`, `campaigns`.`post_type` AS `campaigns.post_type`, `campaigns`.`post_mime_type` AS `campaigns.post_mime_type`, `campaigns`.`comment_count` AS `campaigns.comment_count`,
    `venues`.`ID` AS `venues.ID`, `venues`.`post_author` AS `venues.post_author`, `venues`.`post_date` AS `venues.post_date`, `venues`.`post_date_gmt` AS `venues.post_date_gmt`, `venues`.`post_content` AS `venues.post_content`, `venues`.`post_title` AS `venues.post_title`, `venues`.`post_excerpt` AS `venues.post_excerpt`, `venues`.`post_status` AS `venues.post_status`, `venues`.`comment_status` AS `venues.comment_status`, `venues`.`ping_status` AS `venues.ping_status`, `venues`.`post_password` AS `venues.post_password`, `venues`.`post_name` AS `venues.post_name`, `venues`.`to_ping` AS `venues.to_ping`, `venues`.`pinged` AS `venues.pinged`, `venues`.`post_modified` AS `venues.post_modified`, `venues`.`post_modified_gmt` AS `venues.post_modified_gmt`, `venues`.`post_content_filtered` AS `venues.post_content_filtered`, `venues`.`post_parent` AS `venues.post_parent`, `venues`.`guid` AS `venues.guid`, `venues`.`menu_order` AS `venues.menu_order`, `venues`.`post_type` AS `venues.post_type`, `venues`.`post_mime_type` AS `venues.post_mime_type`, `venues`.`comment_count` AS `venues.comment_count`
    FROM wp_posts AS campaigns
LEFT JOIN wp_postmeta meta1 ON (meta1.meta_key = 'venue' AND campaigns.ID = meta1.post_id)
LEFT JOIN wp_posts venues ON (venues.post_status = 'publish' AND venues.post_type = 'venue' AND venues.ID = meta1.meta_value)
WHERE 1
AND campaigns.post_status = 'publish'
AND campaigns.post_type = 'campaign'
LIMIT 1

Array
(
    [0] => stdClass Object
        (
            [campaigns.ID] => 33
            [campaigns.post_author] => 2
            [campaigns.post_date] => 2012-01-16 19:19:10
            [campaigns.post_date_gmt] => 2012-01-16 19:19:10
            [campaigns.post_content] => Lorem ipsum
            [campaigns.post_title] => Lorem ipsum
            [campaigns.post_excerpt] => 
            [campaigns.post_status] => publish
            [campaigns.comment_status] => closed
            [campaigns.ping_status] => closed
            [campaigns.post_password] => 
            [campaigns.post_name] => lorem-ipsum
            [campaigns.to_ping] => 
            [campaigns.pinged] => 
            [campaigns.post_modified] => 2012-01-16 21:01:55
            [campaigns.post_modified_gmt] => 2012-01-16 21:01:55
            [campaigns.post_content_filtered] => 
            [campaigns.post_parent] => 0
            [campaigns.guid] => http://example.com/?p=33
            [campaigns.menu_order] => 0
            [campaigns.post_type] => campaign
            [campaigns.post_mime_type] => 
            [campaigns.comment_count] => 0
            [venues.ID] => 84
            [venues.post_author] => 2
            [venues.post_date] => 2012-01-16 20:12:05
            [venues.post_date_gmt] => 2012-01-16 20:12:05
            [venues.post_content] => Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
            [venues.post_title] => Lorem ipsum venue
            [venues.post_excerpt] => 
            [venues.post_status] => publish
            [venues.comment_status] => closed
            [venues.ping_status] => closed
            [venues.post_password] => 
            [venues.post_name] => lorem-ipsum-venue
            [venues.to_ping] => 
            [venues.pinged] => 
            [venues.post_modified] => 2012-01-16 20:53:37
            [venues.post_modified_gmt] => 2012-01-16 20:53:37
            [venues.post_content_filtered] => 
            [venues.post_parent] => 0
            [venues.guid] => http://example.com/?p=84
            [venues.menu_order] => 0
            [venues.post_type] => venue
            [venues.post_mime_type] => 
            [venues.comment_count] => 0
        )
)
19
Motin

Die einzige Datenbank, die ich kenne, ist SQLite, abhängig von den Einstellungen, die Sie mit PRAGMA full_column_names und PRAGMA short_column_names konfigurieren. Siehe http://www.sqlite.org/pragma.html

Ansonsten kann ich nur empfehlen, Spalten aus einer Ergebnismenge nach der Ordinalposition und nicht nach dem Spaltennamen abzurufen, wenn es Ihnen zu viel Mühe gibt, die Namen der Spalten in Ihre Abfrage einzugeben.

Dies ist ein gutes Beispiel dafür, warum es ist eine schlechte Praxis, SELECT * - zu verwenden, da Sie irgendwann ohnehin alle Spaltennamen eingeben müssen.

Ich verstehe die Notwendigkeit, Spalten zu unterstützen, die möglicherweise ihren Namen oder ihre Position ändern, aber die Verwendung von Platzhaltern macht härter nicht einfacher.

10
Bill Karwin

Ich bin in einer Art vom selben Boot wie OP - ich habe Dutzende von Feldern aus 3 verschiedenen Tabellen, an denen ich teilnehme, von denen einige denselben Namen haben (z. B. ID, Name usw.). Ich möchte nicht jedes Feld auflisten, daher bestand meine Lösung darin, die Felder, die einen Namen gemeinsam benutzten, als Aliasnamen zu verwenden und select * für diejenigen mit einem eindeutigen Namen zu verwenden.

Zum Beispiel : 

tabelle a: Ich würde, Name, Feld1, Feld2 ...

tabelle b: Ich würde, Name, Feld3, Feld4 ...

wählen Sie eine ID als ID, einen Name als Name, eine. *, b.id als bID, b.name als bName, b. * .....

Beim Zugriff auf die Ergebnisse verwende ich die Aliasnamen für diese Felder und ignoriere die "ursprünglichen" Namen.

Vielleicht nicht die beste Lösung, aber es funktioniert für mich ... Ich benutze Mysql

5
bdt

Verschiedene Datenbankprodukte geben Ihnen unterschiedliche Antworten. Aber du machst dich bereit für den Schmerz, wenn du das sehr weit trägst. Sie sollten die gewünschten Spalten besser auswählen und ihnen eigene Aliasnamen zuweisen, damit die Identität jeder Spalte kristallklar ist und Sie sie in den Ergebnissen unterscheiden können.

5
dkretz

Diese Frage ist in der Praxis sehr nützlich. Es ist nur erforderlich, alle expliziten Spalten in der Softwareprogrammierung aufzulisten, wobei Sie besonders sorgfältig auf alle Bedingungen achten müssen.

Stellen Sie sich vor, beim Debuggen oder versuchen Sie, DBMS als tägliches Office-Tool zu verwenden. Statt einer veränderlichen Implementierung der abstrakten zugrunde liegenden Infrastruktur eines bestimmten Programmierers müssen wir viele SQL-Codes schreiben. Das Szenario ist überall zu finden, z. B. Datenbankkonvertierung, Migration, Verwaltung usw. Die meisten dieser SQL-Anweisungen werden nur einmal ausgeführt und nie wieder verwendet. Geben Sie an, dass alle Spaltennamen nur Zeitverschwendung sind. Und vergessen Sie nicht, dass die Erfindung von SQL nicht nur für Programmierer gedacht ist.

Normalerweise erstelle ich eine Utility-Ansicht mit vorangestellten Spaltennamen. Hier ist die Funktion in pl/pgsql. Es ist nicht einfach, aber Sie können sie in andere Prozedursprachen konvertieren.

-- Create alias-view for specific table.

create or replace function mkaview(schema varchar, tab varchar, prefix varchar)
    returns table(orig varchar, alias varchar) as $$
declare
    qtab varchar;
    qview varchar;
    qcol varchar;
    qacol varchar;
    v record;
    sql varchar;
    len int;
begin
    qtab := '"' || schema || '"."' || tab || '"';
    qview := '"' || schema || '"."av' || prefix || tab || '"';
    sql := 'create view ' || qview || ' as select';

    for v in select * from information_schema.columns
            where table_schema = schema and table_name = tab
    loop
        qcol := '"' || v.column_name || '"';
        qacol := '"' || prefix || v.column_name || '"';

        sql := sql || ' ' || qcol || ' as ' || qacol;
        sql := sql || ', ';

        return query select qcol::varchar, qacol::varchar;
    end loop;

    len := length(sql);
    sql := left(sql, len - 2); -- trim the trailing ', '.
    sql := sql || ' from ' || qtab;

    raise info 'Execute SQL: %', sql;
    execute sql;
end
$$ language plpgsql;

Beispiele:

-- This will create a view "avp_person" with "p_" prefix to all column names.
select * from mkaview('public', 'person', 'p_');

select * from avp_person;
4
Xiè Jìléi

Dafür gibt es keinen SQL-Standard.

Mit der Codegenerierung (entweder bei der Erstellung oder Änderung der Tabellen oder zur Laufzeit) können Sie dies ganz leicht tun:

CREATE TABLE [dbo].[stackoverflow_329931_a](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [col2] [nchar](10) NULL,
    [col3] [nchar](10) NULL,
    [col4] [nchar](10) NULL,
 CONSTRAINT [PK_stackoverflow_329931_a] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [dbo].[stackoverflow_329931_b](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [col2] [nchar](10) NULL,
    [col3] [nchar](10) NULL,
    [col4] [nchar](10) NULL,
 CONSTRAINT [PK_stackoverflow_329931_b] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

DECLARE @table1_name AS varchar(255)
DECLARE @table1_prefix AS varchar(255)
DECLARE @table2_name AS varchar(255)
DECLARE @table2_prefix AS varchar(255)
DECLARE @join_condition AS varchar(255)
SET @table1_name = 'stackoverflow_329931_a'
SET @table1_prefix = 'a_'
SET @table2_name = 'stackoverflow_329931_b'
SET @table2_prefix = 'b_'
SET @join_condition = 'a.[id] = b.[id]'

DECLARE @CRLF AS varchar(2)
SET @CRLF = CHAR(13) + CHAR(10)

DECLARE @a_columnlist AS varchar(MAX)
DECLARE @b_columnlist AS varchar(MAX)
DECLARE @sql AS varchar(MAX)

SELECT @a_columnlist = COALESCE(@a_columnlist + @CRLF + ',', '') + 'a.[' + COLUMN_NAME + '] AS [' + @table1_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table1_name
ORDER BY ORDINAL_POSITION

SELECT @b_columnlist = COALESCE(@b_columnlist + @CRLF + ',', '') + 'b.[' + COLUMN_NAME + '] AS [' + @table2_prefix + COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @table2_name
ORDER BY ORDINAL_POSITION

SET @sql = 'SELECT ' + @a_columnlist + '
,' + @b_columnlist + '
FROM [' + @table1_name + '] AS a
INNER JOIN [' + @table2_name + '] AS b
ON (' + @join_condition + ')'

PRINT @sql
-- EXEC (@sql)
2
Cade Roux

Ich verstehe Ihr Problem vollständig über doppelte Feldnamen.

Ich brauchte das auch, bis ich meine eigene Funktion codiert habe, um es zu lösen. Wenn Sie PHP verwenden, können Sie es verwenden oder Ihre Sprache in der Sprache codieren, für die Sie verwenden, wenn Sie über die folgenden Möglichkeiten verfügen.

Der Trick hier ist, dass mysql_field_table() den Tabellennamen und mysql_field_name() das Feld für jede Zeile im Ergebnis zurückgibt, wenn sie mit mysql_num_fields() angegeben wurde, sodass Sie sie in einem neuen Array mischen können.

Dies fügt alle Spalten vor;)

Grüße,

function mysql_rows_with_columns($query) {
    $result = mysql_query($query);
    if (!$result) return false; // mysql_error() could be used outside
    $fields = mysql_num_fields($result);
    $rows = array();
    while ($row = mysql_fetch_row($result)) { 
        $newRow = array();
        for ($i=0; $i<$fields; $i++) {
            $table = mysql_field_table($result, $i);
            $name = mysql_field_name($result, $i);
            $newRow[$table . "." . $name] = $row[$i];
        }
        $rows[] = $newRow;
    }
    mysql_free_result($result);
    return $rows;
}
2
axelbrz

Sie können dies nicht ohne Aliasing tun, einfach weil, wie wollen Sie ein Feld in der where-Klausel referenzieren, wenn dieses Feld in den 2 oder 3 Tabellen vorhanden ist, an denen Sie teilnehmen? referenzieren.

1
kobejr

Oder Sie können Red Gate SQL Refactor oder SQL-Eingabeaufforderung verwenden, die Ihr SELECT * mit einem Klick auf die Tabulatortaste in Spaltenlisten erweitert

wenn Sie in Ihrem Fall SELECT * FROM A JOIN B ....__ eingeben, gehen Sie zum Ende von *, Tab, voila! Sie werden sehen .__AUSWAHL A.Säule1, A.Säule2, ...., B.Säule1, B.Säule2 FROM A JOIN B

Es ist jedoch nicht frei

1
jerryhung

Ich löste ein ähnliches Problem von mir, indem ich die Felder in den betroffenen Tabellen umbenannte. Ja, ich hatte das Privileg, dies zu tun, und habe verstanden, dass jeder es nicht hat. Ich habe jedem Feld in einer Tabelle, die den Tabellennamen darstellt, ein Präfix hinzugefügt. Damit würde die von OP gepostete SQL unverändert bleiben -

SELECT a.*, b.* FROM TABLE_A a JOIN TABLE_B b USING (some_id);

und immer noch die erwarteten Ergebnisse liefern - einfach feststellen, zu welcher Tabelle die Ausgabefelder gehören.

1
Sam

Für diejenigen, die die MySQL C-API verwenden, gibt es eine direkte Antwort auf Ihre Frage.

In Anbetracht der SQL:

  SELECT a.*, b.*, c.* FROM table_a a JOIN table_b b USING (x) JOIN table_c c USING (y)

Die Ergebnisse von 'mysql_stmt_result_metadata ()' enthalten die Definition Ihrer Felder aus Ihrer vorbereiteten SQL-Abfrage in der Struktur MYSQL_FIELD []. Jedes Feld enthält folgende Daten:

  char *name;                 /* Name of column (may be the alias) */
  char *org_name;             /* Original column name, if an alias */
  char *table;                /* Table of column if column was a field */
  char *org_table;            /* Org table name, if table was an alias */
  char *db;                   /* Database for table */
  char *catalog;              /* Catalog for table */
  char *def;                  /* Default value (set by mysql_list_fields) */
  unsigned long length;       /* Width of column (create length) */
  unsigned long max_length;   /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */

Beachten Sie die Felder: Katalog, Tabelle, Organisationsname

Sie wissen jetzt, welche Felder in Ihrem SQL zu welchem ​​Schema (aka catalog) und zu der Tabelle ... gehören. Dies reicht aus, um jedes Feld anhand einer SQL-Abfrage mit mehreren Tabellen generisch zu identifizieren, ohne einen Aliasnamen verwenden zu müssen.

Ein tatsächliches Produkt SqlYOG soll diese exakten Daten so verwenden, dass es jede Tabelle eines Multi-Table-Joins unabhängig aktualisieren kann, wenn die PK-Felder vorhanden sind.

0
J Jorgenson

Es gibt zwei Möglichkeiten, um dies auf wiederverwendbare Weise zu erreichen. Umbenennen Sie alle Ihre Spalten mit einem Präfix für die Tabelle, aus der sie stammen. Ich habe das schon oft gesehen, aber ich mag es wirklich nicht. Ich finde, es ist überflüssig, verursacht viel Tippen und Sie können immer Aliase verwenden, wenn Sie den Fall eines Spaltennamens abdecken müssen, der einen unklaren Ursprung hat. 

Der andere Weg, den ich Ihnen in Ihrer Situation empfehlen würde, wenn Sie sich dazu verpflichtet fühlen, besteht darin, für jede Tabelle Ansichten zu erstellen, die den Tabellennamen als Alias ​​bezeichnen. Dann treten Sie gegen diese Ansichten und nicht gegen die Tabellen ein. Auf diese Weise können Sie * frei verwenden, wenn Sie möchten, die Originaltabellen können bei Bedarf mit den ursprünglichen Spaltennamen verwendet werden. Dies erleichtert auch das Schreiben nachfolgender Abfragen, da Sie die Umbenennung bereits in den Ansichten ausgeführt haben.

Schließlich ist mir nicht klar, warum Sie wissen müssen, aus welcher Tabelle jede der Spalten stammt. Ist das wichtig? Was letztendlich zählt, sind die Daten, die sie enthalten. Ob die UserID aus der User-Tabelle oder der UserQuestion-Tabelle stammt, spielt keine Rolle. Es ist natürlich wichtig, wann Sie es aktualisieren müssen, aber zu diesem Zeitpunkt sollten Sie Ihr Schema bereits gut genug kennen, um dies festzustellen.

0
RedFilter

Dieses Thema ist kürzlich in NodeJS und Postgres aufgetreten.

ES6-Ansatz

Ich kenne keine RDBMS-Funktionen, die diese Funktionalität bieten. Daher habe ich ein Objekt erstellt, das alle meine Felder enthält, z. B .:

const schema = { columns: ['id','another_column','yet_another_column'] }

Definiert ein Reduzierstück, um die Zeichenfolgen zusammen mit einem Tabellennamen zu verketten:

const prefix = (table, columns) => columns.reduce((previous, column) => {
  previous.Push(table + '.' + column + ' AS ' + table + '_' + column);
  return previous;
}, []);

Dies gibt ein Array von Strings zurück. Nennen Sie es für jede Tabelle und kombinieren Sie die Ergebnisse:

const columns_joined = [...prefix('tab1',schema.columns), ...prefix('tab2',schema.columns)];

Ausgabe der endgültigen SQL-Anweisung:

console.log('SELECT ' + columns_joined.join(',') + ' FROM tab1, tab2 WHERE tab1.id = tab2.id');
0
Blair

Ich entwickle aus dieser Lösung so würde ich das Problem angehen:

Erstellen Sie zuerst eine Liste aller AS-Anweisungen:

DECLARE @asStatements varchar(8000)

SELECT @asStatements = ISNULL(@asStatements + ', ','') + QUOTENAME(table_name) + '.' + QUOTENAME(column_name) + ' AS ' + '[' + table_name + '.' + column_name + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TABLE_A' OR TABLE_NAME = 'TABLE_B'
ORDER BY ORDINAL_POSITION

Dann verwenden Sie es in Ihrer Suchanfrage:

EXEC('SELECT ' + @asStatements + ' FROM TABLE_A a JOIN TABLE_B b USING (some_id)');

Dies erfordert jedoch möglicherweise Änderungen, da etwas Ähnliches nur in SQL Server getestet wird. Dieser Code funktioniert jedoch nicht genau in SQL Server, da USING nicht unterstützt wird.

Bitte kommentieren Sie, ob Sie diesen Code für z. MySQL.

0
Antonio

Ich habe eine Lösung implementiert, die auf der Antwort basiert und die Verwendung von Dummy- oder Sentinel-Spalten im Knoten vorschlägt. Sie würden es verwenden, indem Sie SQL wie folgt generieren:

select 
    s.*
  , '' as _prefix__creator_
  , u.*
  , '' as _prefix__speaker_
  , p.*
from statements s 
  left join users u on s.creator_user_id = u.user_id
  left join persons p on s.speaker_person_id = p.person_id

Anschließend wird die Zeile nachbearbeitet, die Sie von Ihrem Datenbanktreiber erhalten, z. B. addPrefixes(row).

Implementierung (basierend auf der fields/rows, die von meinem Treiber zurückgegeben wird, sollte aber für andere DB-Treiber leicht zu ändern sein):

const PREFIX_INDICATOR = '_prefix__'
const STOP_PREFIX_INDICATOR = '_stop_prefix'

/** Adds a <prefix> to all properties that follow a property with the name: PREFIX_INDICATOR<prefix> */
function addPrefixes(fields, row) {
  let prefix = null
  for (const field of fields) {
    const key = field.name
    if (key.startsWith(PREFIX_INDICATOR)) {
      if (row[key] !== '') {
        throw new Error(`PREFIX_INDICATOR ${PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = key.substr(PREFIX_INDICATOR.length)
      delete row[key]
    } else if (key === STOP_PREFIX_INDICATOR) {
      if (row[key] !== '') {
        throw new Error(`STOP_PREFIX_INDICATOR ${STOP_PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = null
      delete row[key]
    } else if (prefix) {
      const prefixedKey = prefix + key
      row[prefixedKey] = row[key]
      delete row[key]
    }
  }
  return row
}

Prüfung:

const {
  addPrefixes,
  PREFIX_INDICATOR,
  STOP_PREFIX_INDICATOR,
} = require('./BaseDao')

describe('addPrefixes', () => {
  test('adds prefixes', () => {
    const fields = [
      {name: 'id'},
      {name: PREFIX_INDICATOR + 'my_prefix_'},
      {name: 'foo'},
      {name: STOP_PREFIX_INDICATOR},
      {name: 'baz'},
    ]
    const row = {
      id: 1,
      [PREFIX_INDICATOR + 'my_prefix_']: '',
      foo: 'bar',
      [STOP_PREFIX_INDICATOR]: '',
      baz: 'spaz'
    }
    const expected = {
      id: 1,
      my_prefix_foo: 'bar',
      baz: 'spaz',
    }
    expect(addPrefixes(fields, row)).toEqual(expected)
  })
})
0
Carl G

Ich verwende Excel, um die Prozedur zu verketten. Zum Beispiel wähle ich zuerst * aus und hole alle Spalten, füge sie in Excel ein. Dann schreiben Sie den Code, den ich brauche, um die Spalte zu umgeben. Angenommen, ich musste vor einer Reihe von Spalten werben. Ich würde meine Felder in der a-Spalte und "als prev_" in Spalte B und meine Felder wieder in Spalte c haben. In Spalte d hätte ich eine Spalte.

Verwenden Sie dann concatanate in Spalte e und fügen Sie sie zusammen, wobei Sie Leerzeichen einschließen. Dann schneiden Sie es aus und fügen es in Ihren SQL-Code ein. Ich habe diese Methode auch verwendet, um case-Anweisungen für dasselbe Feld und andere längere Codes zu erstellen, die ich für jedes Feld in einer Tabelle mit mehreren Hundert Feldern ausführen muss.

0
Nathan Michael

select * führt in der Regel zu fehlerhaftem Code, da neue Spalten hinzugefügt werden oder die Reihenfolge der Spalten in Tabellen häufig geändert wird, was select * in der Regel auf sehr subtile Weise unterbricht. Das Auflisten von Spalten ist also die richtige Lösung.

Sie sind sich nicht sicher, wie Sie Ihre Abfrage ausführen sollen, aber in sqlserver können Sie Spaltennamen aus syscolumns auswählen und die select-Klausel dynamisch erstellen.

0
Kozyarchuk

Wenn Sie sich über Schemaänderungen Sorgen machen, kann dies für Sie funktionieren: 1. Führen Sie eine Abfrage 'DESCRIBE table' für alle betroffenen Tabellen aus. 2. Verwenden Sie die zurückgegebenen Feldnamen, um dynamisch eine Zeichenfolge aus Spaltennamen zu erstellen, denen der ausgewählte Alias ​​vorangestellt ist.

0
Chris Jacob