269

これが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.* によって返されるすべての列の前に 'something' を付ける」ということです。これは可能ですか、それとも運が悪いですか?

編集

使用しないSELECT *などのアドバイスは有効なアドバイスですが、私のコンテキストには関係ありません。そのため、当面の問題に固執してください-接頭辞(SQLクエリで指定された定数)を結合のテーブル?

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

4

24 に答える 24

111

あなたの質問に対する答えは「いいえ」のようですが、使用できるハックの 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

これはあなたの質問に正確に答えるものではないことは承知していますが、コーダーである場合、これは重複する列名を持つテーブルを分離するための優れた方法です。これが誰かに役立つことを願っています。

于 2012-03-29T13:16:43.963 に答える
35

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

于 2008-12-01T03:42:24.863 に答える
30

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

コード生成によってこれを実現するための PHP (Wordpress) 関数と、その使用方法の例を次に示します。この例では、高度なカスタム フィールドフィールドを介して参照された、関連する 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
        )
)
于 2012-01-19T16:17:05.823 に答える
15

PRAGMA full_column_namesと で構成する設定に応じて、これを行うことがわかっている唯一のデータベースは SQLite ですPRAGMA short_column_nameshttp://www.sqlite.org/pragma.htmlを参照してください。

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

これは、使用するのが悪い方法SELECT *である理由の良い例です。最終的には、とにかくすべての列名を入力する必要があるからです。

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

于 2008-12-01T03:39:56.270 に答える
7

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

例えば ​​:

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

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

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

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

たぶん最善の解決策ではありませんが、それは私にとってはうまくいきます....私はmysqlを使用しています

于 2008-12-02T14:06:34.710 に答える
4

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

于 2008-12-01T03:19:07.780 に答える
4

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

それを解決するために独自の関数をコーディングするまで、それも必要でした。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;
}
于 2013-03-22T05:34:42.137 に答える
3

これに対する 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)
于 2008-12-01T04:58:11.933 に答える
2

最近、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');
于 2018-03-21T04:42:42.643 に答える
2

または、Red Gate SQL Refactor または SQL Prompt を使用して、Tab ボタンをクリックするだけで SELECT * を列リストに展開できます。

したがって、あなたの場合、SELECT * FROM A JOIN B ...と入力すると、*の最後に移動し、タブボタン、ほら!SELECT A.column1, A.column2, .... , B.column1, B.column2 FROM A JOIN B が表示されます

無料じゃないけど

于 2008-12-02T14:44:50.313 に答える
1

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

于 2009-07-08T06:38:30.567 に答える
1

select * は通常、新しい列が追加される傾向があるか、テーブル内の列の順序が頻繁に変更される傾向があり、select * が非常に微妙な方法で壊れるため、通常は悪いコードになります。したがって、列をリストすることが正しい解決策です。

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

于 2008-12-01T03:24:31.420 に答える
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'));
于 2018-06-22T20:41:24.500 に答える
1

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

于 2011-12-14T05:45:54.093 に答える
1

ノードでダミーまたはセンチネル列を使用することを提案する回答に基づいて、ソリューションを実装しました。次のような 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)
  })
})
于 2018-11-01T21:08:10.517 に答える
1

この解決策から発展して、これは私が問題にアプローチする方法です:

まず、すべての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 などでこのコードをテスト/修正できる場合は、コメントしてください。

于 2015-09-09T17:02:10.020 に答える
1

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 フィールドが存在する場合、複数テーブル結合の各テーブルを個別に更新できるような方法でこの正確なデータを使用することが示されています。

于 2010-04-07T22:33:49.040 に答える
1

これを再利用可能な方法で実現するには、2 つの方法が考えられます。1 つは、元のテーブルのプレフィックスを使用してすべての列の名前を変更することです。私はこれを何度も見てきましたが、本当に好きではありません。これは冗長で、大量の入力が必要であり、起源が不明確な列名のケースをカバーする必要がある場合は、いつでもエイリアスを使用できます。

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

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

于 2008-12-01T04:13:01.463 に答える