SQL選択結合:すべての列の前に 'prefix。*'を付けることはできますか?


206

これはSQLで可能かどうか疑問に思っています。2つのテーブルAとBがあり、テーブルAで選択を行い、テーブルBで結合するとします。

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

テーブルAに列「a_id」、「name」、および「some_id」があり、テーブルBに「b_id」、「name」、および「some_id」がある場合、クエリは列「a_id」、「name」、「some_id」を返します'、' b_id '、' name '、' some_id '。すべての列を個別にリストせずにテーブルBの列名にプレフィックスを付ける方法はありますか?これに相当するもの:

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);

しかし、前述のように、すべての列をリストしないため、次のようになります。

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

基本的に言うと、「b。*によって返されるすべての列に「何か」のプレフィックスを付けます」。これは可能ですか、それとも不運ですか?

よろしくお願いします!

編集:SELECT *を使用しないなどのアドバイスは有効なアドバイスですが、私のコンテキストには関係ありませんので、手元の問題に固執してください-すべてのプレフィックス(SQLクエリで指定された定数)を追加することは可能ですか?結合のテーブルの列名?

編集:私の最終的な目標は、結合を使用して2つのテーブルでSELECT *を実行し、結果セットで取得した列の名前から、どの列がテーブルAから来て、どの列が来たかを知ることができるようにすることですテーブルBから。ここでも、列を個別にリストする必要はありません。SELECT*を実行できる必要があります。


クエリの結果はどうなると思いますか?私は混乱しています
GregD 2008

GregD:b。*から出てくるすべての列名の前に、指定した定数を付けたいです。たとえば、「名前」と「番号」の代わりに、たとえば「special_」接頭辞を指定して、「special_name」と「special_number」を取得したいとします。ただし、列ごとに個別にこれを実行する必要はありません。
foxdonut 2008

6
クイックSELECTを実行して複数のテーブルの列を表示するとき、SELECT 'AAAAA'、A. *、 'BBBBB'、B. * FROM TableA AS A JOIN TableB AS B ON A.ID = B.IDを実行して、行に沿ってスキャンするときは、少なくともテーブル識別子がある
Kristen

回答:


35

ここでは2つの状況が考えられます。最初に、データベースに関係なく一般的に使用できるSQL標準があるかどうかを確認します。いいえ、ありません。次に、特定のdbms製品に関して知りたいと思います。次に、それを識別する必要があります。しかし、おそらく最も可能性の高い答えは、「a.id、b.id」のようなものが返されることだと思います。これは、SQL式で列を識別するために必要な方法だからです。そして、デフォルトが何であるかを知る最も簡単な方法は、そのようなクエリを送信して、何が返ってくるかを確認することです。ドットの前にあるプレフィックスを指定する場合は、たとえば「SELECT * FROM a AS my_alias」を使用できます。


11
これがあなたの質問にどのように答えるかはわかりません。MS SQL Serverを使用していて、テーブル名の後にエイリアスを追加しても、結果セットの列名にエイリアスが追加されません。
パイエゴ2015年

74

あなたの質問への答えはノーであるようですが、あなたが使用できる1つのハックは、各新しいテーブルを分離するためにダミー列を割り当てることです。これは、PythonやPHPなどのスクリプト言語で列のリストの結果セットをループする場合に特に効果的です。

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

私はこれがあなたの質問に正確に答えていないことを理解していますが、あなたがコーダーであれば、これは重複した列名を持つテーブルを分離する素晴らしい方法です。これが誰かを助けることを願っています。


24

これが必要な理由は完全に理解できます。少なくとも、多くの内部結合を含め、結合する必要のあるテーブルがたくさんある場合、ラピッドプロトタイピングの際に便利です。2番目の「joinedtable。*」フィールドのワイルドカードで列名が同じになるとすぐに、メインテーブルのフィールド値がjointabletableの値で上書きされます。エイリアスを使用してテーブルフィールドを何度も手動で指定する必要がある場合、エラーが発生しやすく、イライラし、DRYに違反します...

これは、コード生成を通じてこれを実現するためのPHP(Wordpress)関数と、その使用方法の例です。この例では、高度なカスタムフィールドフィールドを通じて参照された関連ワードプレス投稿のフィールドを提供するカスタムクエリを迅速に生成するために使用されます。

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>";
}

出力:

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
        )
)

13

私はそれがこれを行う知っている唯一のデータベースは、あなたが設定した設定に応じて、SQLiteのであるPRAGMA full_column_namesPRAGMA short_column_nameshttp://www.sqlite.org/pragma.htmlを参照してください

それ以外の場合、クエリに列の名前を入力するのが面倒であれば、結果セットの列を列名ではなく序数でフェッチすることをお勧めします。

これは、使用するのが悪い習慣のSELECT *良い例です。結局のところ、いずれにしてもすべての列名を入力する必要があるためです。

名前や位置を変更する可能性のある列をサポートする必要性を理解していますが、ワイルドカードを使用すると、が難しくなり、簡単ではありません。


2
full_column_namesshort_column_namesはどちらもSQLiteでは非推奨です
isanae 2016年

6

私はOPと同じボートのようなものです-私が参加している3つの異なるテーブルからの多数のフィールドがあり、それらのいくつかは同じ名前(つまり、ID、名前など)を持っています。各フィールドをリストしたくないので、私の解決策は、名前を共有するフィールドにエイリアスを付け、一意の名前を持つフィールドにはselect *を使用することでした。

例えば ​​:

テーブルa:id、name、field1、field2 ...

テーブルb:id、name、field3、field4 ...

a.idをaID、a.nameをaName、aとして選択します。*、b.idはbID、b.nameはbName、b。* .....

結果にアクセスするとき、私はこれらのフィールドのエイリアス名を使用し、「元の」名前は無視します。

多分最善の解決策ではないかもしれませんが、私にとってはうまくいきます...私はmysqlを使用しています


5

異なるデータベース製品はあなたに異なる答えを与えます。しかし、これを非常に遠くに運ぶと、あなたは傷ついた状態に陥ります。必要な列を選択し、それらに独自のエイリアスを与えて、各列のIDが明確になり、結果でそれらを区別できるようにする方がはるかに優れています。


1
ポイントが取られましたが、ここでの私の目標は非常に一般的なものであるため、明示的でなくても問題ありません。実際、具体的にする必要があるのは問題でしょう
foxdonut 2008

以下の追加の提出を参照してください。dot.notationを使用できますが、これはおそらくデフォルトで取得されるものですか?
dkretz 2008

読みやすくするために重要です。私は、CTEプロセスに長けているため、これを今すぐ実現したいと考えていました。例。CTE_A-> CTE_B-> CTE_C-> CTE_D->選択/挿入最後の選択ステートメントとパフォーマンスが考慮されなくなるまで、必要な列を指定する必要はありません。
ThomasRones、

5

この質問は、実際には非常に役立ちます。ソフトウェアプログラミングのすべての明示的な列をリストするだけでよく、すべての条件に対処するために特に注意を払います。

特定のプログラマの抽象的な基盤となるインフラストラクチャの変更可能な実装の代わりに、デバッグ時、または日常のオフィスツールとしてDBMSを使用しようとする場合を想像してください。多くのSQLをコーディングする必要があります。シナリオは、データベースの変換、移行、管理など、あらゆる場所で見つけることができます。これらのSQLのほとんどは1回だけ実行され、再度使用されることはありません。すべての列名は時間の無駄です。SQLの発明は、プログラマーが使用するためだけのものではないことを忘れないでください。

通常、列名をプレフィックスとしてユーティリティビューを作成します。これはpl / pgsqlの関数です。簡単ではありませんが、他のプロシージャ言語に変換できます。

-- 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;

例:

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

select * from avp_person;

3

フィールド名の重複に関する問題を完全に理解しました。

それを解決するために自分の関数をコーディングするまで、私もそれが必要でした。PHPを使用している場合はそれを使用できます。または、以下の機能があれば、使用している言語でPHPをコーディングできます。

ここでの秘訣mysql_field_table()は、テーブル名とmysql_field_name()各行のフィールドが返された場合、mysql_num_fields()それらを新しい配列に混在させることができるためです。

これはすべての列にプレフィックスを付けます;)

よろしく、

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

このためのSQL標準はありません。

ただし、コード生成を使用すると(テーブルの作成時または変更時にオンデマンドで、または実行時に)、これを非常に簡単に行うことができます。

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)

これは機能しますが、問題はかなりばかげています。なぜユニオンまたはサブクエリを実行しないのですか?なぜ結合し、それでも列名にテーブル接頭辞が必要なのですか?
D3vtr0n 2008

ケイド:情報をありがとう、それは面白いです。残念ながら、私の場合、データベースの生成/変更はオプションではありません。Devtron:クエリから返される情報をオブジェクトのさまざまなプロパティにマッピングしようとすると、その情報は非常に役立ちます。
foxdonut 2008

1
異なるテーブルの列名は同じでも、同じ値が含まれていない場合があります。したがって、ビューまたは派生テーブル(すべての一意の列名を持つ必要があります)でそれらを区別するためにそれらをプレフィックスする必要があります。
Cade Roux

@Frederic、コードはどこかに存在する必要があります-これはコードを生成するだけです。繰り返しますが、これは開発中に一度、または実行時に動的に行うことができます。
Cade Roux

1

これを再利用可能な方法で実現するには、2つの方法が考えられます。1つは、すべての列の名前を、それらが由来するテーブルの接頭辞で変更することです。これは何度も見たことがありますが、本当に嫌いです。列名が原因が明確でない場合に対応する必要がある場合は、冗長であり、多くの入力が必要になるため、エイリアスをいつでも使用できます。

これを確認することに専念している場合は、状況に応じて行うことをお勧めするもう1つの方法は、テーブル名にエイリアスを設定する各テーブルのビューを作成することです。次に、テーブルではなく、それらのビューに対して結合します。そうすることで、必要に応じて*を自由に使用でき、必要に応じて元の列名を持つ元のテーブルを自由に使用できます。また、ビューで名前の変更作業を既に行っているため、後続のクエリを簡単に作成できます。

最後に、各列がどのテーブルから来たのかを知る必要がある理由は明らかではありません。これは問題ですか?最終的に重要なのは、そこに含まれるデータです。UserIDがUserテーブルからのものか、UserQuestionテーブルからのものかは、実際には重要ではありません。もちろん、いつ更新する必要があるかは重要ですが、その時点で、スキーマを十分に理解して、それを決定する必要があります。


「最後に、なぜ各列がどのテーブルから来たのかを知る必要がある理由はわかりません。これは問題ですか?」<-11年後の1つの使用例は、Goでの構造体スキャンです。
リーベンソン、

1

または、Red Gate SQLリファクタリングまたはSQLプロンプトを使用して、タブボタンをクリックするだけでSELECT *を列リストに展開できます。

したがって、あなたのケースでは、SELECT * FROM A JOIN B ...と入力すると、*、タブボタンの最後に移動します。SELECT A.column1、A.column2、....、B.column1、B.column2 FROM A JOIN Bが表示されます

それは無料ではありません


1

結合する2つまたは3つのテーブルにそのフィールドが存在する場合、そのフィールドがwhere句のフィールドをどのように参照するのかという理由だけで、エイリアスなしでこれを行うことはできません。どのmysqlを参照しようとしているのかはmysqlにはわかりません。


1

関連するテーブルのフィールドの名前を変更することで、同様の問題を解決しました。はい、私にはこれを行う特権があり、誰もがそれを持っているわけではないことを理解しています。テーブル名を表すテーブル内の各フィールドにプレフィックスを追加しました。したがって、OPによってポストされたSQLは変更されません。

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

それでも期待される結果が得られます-出力フィールドが属するテーブルを簡単に特定できます。


0

新しい列が追加される傾向があるか、テーブルの列の順序が頻繁に変更される傾向があるため、select *は通常、不適切なコードになります。したがって、列をリストすることは適切なソリューションです。

クエリの方法については、mysqlについてはわかりませんが、sqlserverではsyscolumnsから列名を選択し、select句を動的に構築できます。


ポイントは取られましたが、私のコンテキストでは、汎用的で動的なものが必要なので、実際、私のコードは、追加/並べ替え/追加される新しい列に適応します。列を個別にリストする必要はありません。
foxdonut 2008

5
syscolumnsから選択してselectステートメントを動的に構築することはひどいハックであり、私はそれを本番環境で推奨しません。
ジュリエット

0

スキーマの変更が心配な場合は、これでうまくいく可能性があります。1.関係するすべてのテーブルで「DESCRIBEテーブル」クエリを実行します。2.返されたフィールド名を使用して、選択したエイリアスを前に付けた列名の文字列を動的に構築します。


0

MySQL C-APIを使用する人のためのあなたの質問への直接の答えがあります。

SQLを考える:

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

'mysql_stmt_result_metadata()'の結果は、準備したSQLクエリからのフィールドの定義を構造MYSQL_FIELD []に与えます。各フィールドには次のデータが含まれています。

  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 */

フィールドに注意してください:catalog、table、org_name

これで、SQLのどのフィールドがどのスキーマ(別名カタログ)とテーブルに属しているかがわかります。これは、エイリアスを設定することなく、複数テーブルのSQLクエリから各フィールドを一般的に識別するのに十分です。

実際の製品SqlYOGは、PKフィールドが存在する場合に、複数テーブル結合の各テーブルを個別に更新できるような方法でこの正確なデータを使用することを示しています。


0

このソリューションから開発した、これが私が問題に取り組む方法です:

まず、すべてのASステートメントのリストを作成します。

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

次に、クエリで使用します。

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

ただし、SQL Serverでのみ同様のテストが行​​われるため、変更が必要になる場合があります。しかし、USINGがサポートされていないため、このコードはSQL Serverでは正確に機能しません。

MySQLなどでこのコードをテスト/修正できる場合はコメントしてください。


0

最近、NodeJSとPostgresでこの問題に遭遇しました。

ES6アプローチ

この機能を提供するRDBMS機能はありません。そのため、すべてのフィールドを含むオブジェクトを作成しました。例:

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

文字列をテーブル名と連結するレデューサーを定義しました:

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

これは文字列の配列を返します。テーブルごとに呼び出し、結果を結合します。

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

最後のSQLステートメントを出力します。

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

ありえない!これは一部のハックSQLインジェクションであり、式では機能しません。
ratijas

0

ノードでダミーまたはセンチネル列を使用することを提案する回答に基づいてソリューションを実装しました。次のようなSQLを生成して使用します。

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

次に、データベースドライバーから取得した行を後処理しますaddPrefixes(row)

実装(私のドライバーから返されたfields/ rowsに基づいていますが、他のDBドライバー用に簡単に変更できるはずです):

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
}

テスト:

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

Excelを使用して手順を連結します。たとえば、最初に*を選択してすべての列を取得し、Excelに貼り付けます。次に、列を囲むために必要なコードを記述します。たくさんのコラムを前に宣伝する必要があったとしましょう。私のフィールドはa列にあり、「as prev_」は列Bにあり、私のフィールドは再び列cにあります。列dには列があります。

次に、e列で連結を使用し、それらを結合して、スペースが含まれるようにします。次に、これをSQLコードにカットアンドペーストします。また、このメソッドを使用して、同じフィールドと、何百ものフィールドテーブルの各フィールドに対して実行する必要がある他の長いコードのケースステートメントを作成しました。


0

postgresでは、代わりにjson関数を使用してjsonオブジェクトを返します。次に、クエリを実行した後、_jsonサフィックスを使用してフィールドをjson_decodeします。

IE:

select row_to_json(tab1.*),tab1_json, row_to_json(tab2.*) tab2_json 
 from tab1
 join tab2 on tab2.t1id=tab1.id

次に、PHP(または他の言語)では、返された列をループ処理し、それらに「_json」サフィックスがある場合はそれらをjson_decode()して(また、サフィックスを削除します。最後に、すべてを含む「tab1」というオブジェクトを取得します。 tab1フィールド、およびすべてのtab2フィールドを含む「tab2」と呼ばれる別のフィールド。


-1

PHP 7.2 + MySQL / Mariadb

MySQLは同じ名前の複数のフィールドを送信します。ターミナルクライアントでも。ただし、連想配列が必要な場合は、自分でキーを作成する必要があります。

オリジナルの@axelbrzに感謝します。私はそれを新しいphpに移植し、少し整理しました:

function mysqli_rows_with_columns($link, $query) {
    $result = mysqli_query($link, $query);
    if (!$result) {
        return mysqli_error($link);
    }
    $field_count = mysqli_num_fields($result);
    $fields = array();
    for ($i = 0; $i < $field_count; $i++) {
        $field = mysqli_fetch_field_direct($result, $i);
        $fields[] = $field->table . '.' . $field->name; # changed by AS
        #$fields[] = $field->orgtable . '.' . $field->orgname; # actual table/field names
    }
    $rows = array();
    while ($row = mysqli_fetch_row($result)) {
        $new_row = array();
        for ($i = 0; $i < $field_count; $i++) {
            $new_row[$fields[$i]] = $row[$i];
        }
        $rows[] = $new_row;
    }
    mysqli_free_result($result);
    return $rows;
}

$link = mysqli_connect('localhost', 'fixme', 'fixme', 'fixme');
print_r(mysqli_rows_with_columns($link, 'select foo.*, bar.* from foo, bar'));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.