programing

SQL 선택 조인: 모든 열 앞에 '접두사'로 접두사를 지정할 수 있습니다.*'?

magicmemo 2023. 5. 16. 22:28
반응형

SQL 선택 조인: 모든 열 앞에 '접두사'로 접두사를 지정할 수 있습니다.*'?

저는 이것이 SQL에서 가능한지 궁금합니다.두 개의 테이블 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의 열 이름 앞에 접두사를 붙일 수 있는 방법이 있습니까?이에 상응하는 것:

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 쿼리에 지정된 상수)를 추가할 수 있습니까?

저의 궁극적인 목표는SELECT *조인이 있는 두 개의 테이블에서 결과 집합에 있는 열 이름을 통해 어떤 열이 A 테이블에서 왔고 어떤 열이 B 테이블에서 왔는지 알 수 있습니다.다시 말씀드리지만, 열을 개별적으로 나열할 필요가 없습니다. 다음 작업을 수행할 수 있어야 합니다.SELECT *.

당신의 질문에 대한 대답은 아니오인 것처럼 보이지만, 당신이 사용할 수 있는 한 가지 해킹은 각각의 새로운 테이블을 분리하기 위해 더미 열을 할당하는 것입니다.이 기능은 특히 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

이것이 당신의 질문에 정확하게 답하지 않는다는 것을 알지만, 만약 당신이 코더라면 이것은 중복된 열 이름을 가진 테이블을 분리하는 좋은 방법입니다.

저는 여기서 두 가지 가능한 상황을 봅니다.먼저 데이터베이스에 관계없이 일반적으로 사용할 수 있는 SQL 표준이 있는지 여부를 알고자 합니다.아니요, 없습니다.둘째, 특정 dbms 제품과 관련하여 알고자 합니다.그럼 당신은 그것을 확인해야 합니다.하지만 가장 가능성 있는 대답은 "a.id , b.id "과 같은 것을 찾을 수 있다는 것입니다. SQL 식에서 열을 식별하는 방법이 필요하기 때문입니다.기본값이 무엇인지 알아내는 가장 쉬운 방법은 이러한 쿼리를 제출하고 무엇을 얻을 수 있는지 확인하는 것입니다.점 앞에 오는 접두사를 지정하려면 예를 들어 "SELECT * FROM a AS my_alias"를 사용할 수 있습니다.

저는 이것이 왜 필요한지 완전히 이해합니다. 적어도 저에게는 많은 내부 접합을 포함하여 결합해야 하는 테이블이 많은 경우 빠른 프로토타이핑 중에 유용합니다.두 번째 "결합된 테이블"에서 열 이름이 동일한 즉시필드 와일드카드, 기본 테이블의 필드 값은 조인된 테이블 값으로 재정의됩니다.반복해서 별칭이 있는 테이블 필드를 수동으로 지정해야 할 경우 오류가 발생하기 쉽고, 답답하며, 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
        )
)

(SQLite 이를 수행하는 유일한 입니다.PRAGMA full_column_names그리고.PRAGMA short_column_nameshttp://www.sqlite.org/pragma.html 을 참조하십시오.

그렇지 않으면 쿼리에 열 이름을 입력하는 것이 너무 번거로우면 열 이름이 아닌 순서형 위치로 열을 가져오는 것이 좋습니다.

이것은 사용하는 것이 좋지 않은 이유를 보여주는 좋은 예입니다. 결국 모든 열 이름을 입력해야 하기 때문입니다.

이름이나 위치를 변경할 수 있는 열을 지원해야 하는 필요성은 이해하지만 와일드카드를 사용하면 이 작업이 쉽지 않고 어려워집니다.

postgres에서는 json 함수를 사용하여 json 객체를 반환합니다.그런 다음 쿼리 후 _json 접미사를 사용하여 필드를 _json_decode합니다.

IE:

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

그런 다음 PHP(또는 다른 언어)에서 "_json" 접미사가 있으면 반환된 열과 json_decode()를 반복합니다.결국, 저는 모든 탭1 필드를 포함하는 "tab1"이라는 개체와 모든 탭2 필드를 포함하는 "tab2"라는 개체를 얻습니다.

이 질문은 실제로 매우 유용합니다.소프트웨어 프로그래밍에서 명시적인 모든 열을 나열하기만 하면 되며, 모든 조건을 처리하기 위해 특히 주의를 기울입니다.

디버깅하거나 DBMS를 일일 사무실 도구로 사용하려고 할 때 특정 프로그래머의 추상적인 기본 인프라를 변경할 수 있는 구현 대신 많은 SQL을 코딩해야 한다고 상상해 보십시오.이 시나리오는 데이터베이스 변환, 마이그레이션, 관리 등 모든 곳에서 찾을 수 있습니다.대부분의 SQL은 한 번만 실행되고 다시는 사용되지 않습니다. 모든 열 이름은 시간 낭비입니다.그리고 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;

저는 OP와 같은 처지에 있습니다 - 저는 제가 가입하고 있는 3개의 다른 테이블에 있는 수십 개의 필드가 있으며, 그 중 일부는 같은 이름(즉,)을 가지고 있습니다.ID, 이름 등).각 필드를 나열하지 않기 때문에 이름을 공유하는 필드에 별칭을 지정하고 고유한 이름을 가진 필드에 대해 select *를 사용하는 것이 해결책이었습니다.

예:

테이블 a: ID, 이름, 필드 1, 필드 2...

테이블 b: ID, 이름, 필드 3, 필드 4...

a.id 을 aID로, a.name 을 aName으로, b.id 을 a. *, b.name 을 bID로, ▁as 을 bName으로, b. *...로 선택합니다.

결과에 액세스할 때 이 필드의 별칭을 사용하고 "원래" 이름은 무시합니다.

최선의 해결책은 아닐 수도 있지만 저에게는 효과가 있습니다.나는 mysql을 사용합니다.

데이터베이스 제품에 따라 다른 답변이 제공됩니다. 하지만 이 문제를 너무 멀리하면 손해를 볼 수 있습니다.원하는 열을 선택하고 고유한 별칭을 지정하여 각 열의 ID를 명확하게 식별하고 결과에서 구분할 수 있습니다.

중복된 필드 이름에 대한 당신의 문제를 완전히 이해합니다.

그것을 해결하기 위해 제 기능을 코딩하기 전까지는 그것도 필요했습니다.만약 당신이 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;
}

이에 대한 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)

사용합니다to_jsonbPostgre에서 기능SQL 13 - 조인된 테이블의 모든 필드를 단일 열로 가져옵니다.

select
  TABLE_A.*,
  to_jsonb(TABLE_B.*) as b,
  to_jsonb(TABLE_C.*) as c
from TABLE_A
left join TABLE_B on TABLE_B.a_id=TABLE_A.id
left join TABLE_C on TABLE_C.a_id=TABLE_A.id
where TABLE_A.id=1

결과적으로 당신은 TAB의 수를 얻게 될 것입니다.LE_A 열 더하기 b 및 c 열:

이드 이름. 약간의_다른_col b c
1 어떤 이름 어떤 다른 가치 {"id":1",a_id":1",prop":"value"} {"id":1",a_id":1",prop":"value"}
1 다른 이름 다른 값 {"id":1",a_id":1",prop":"value"} {"id":1",a_id":1",prop":"value"}

b 및 c 열을 구문 분석하여 개체로 변환하기만 하면 됩니다.

또는 Red Gate SQL Refactor 또는 SQL Prompt를 사용하여 Tab 버튼을 클릭하면 SELECT *를 열 목록으로 확장할 수 있습니다.

그래서 당신의 경우, 만약 당신이 선택 * FROM A JOIN B를 입력한다면...*의 끝으로 이동합니다. 탭 버튼, voila!조인 B에서 선택 A.column1, A.column2, ..., B.column1, B.column2가 표시됩니다.

무료는 아니지만요.

저는 관련된 표의 필드 이름을 변경하여 저의 비슷한 문제를 해결했습니다.네, 저는 이것을 할 수 있는 특권이 있었고 모든 사람들이 그것을 가지고 있지 않을 수도 있다는 것을 이해합니다.표 이름을 나타내는 표 내의 각 필드에 접두사를 추가했습니다.따라서 OP가 게시한 SQL은 변경되지 않은 상태로 유지됩니다.

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

출력 필드가 어떤 테이블에 속하는지 쉽게 식별할 수 있는 예상 결과를 제공합니다.

최근 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');

select *는 새 열이 추가되는 경향이 있거나 테이블에서 열 순서가 매우 자주 변경되기 때문에 일반적으로 매우 미묘한 방식으로 select *를 구분합니다.따라서 열을 나열하는 것이 올바른 해결책입니다.

쿼리를 수행하는 방법에 대해서는 mysql에 대해 잘 모르지만 sqlserver에서는 syscolumn에서 열 이름을 선택하고 select 절을 동적으로 작성할 수 있습니다.

재사용 가능한 방법으로 이를 실현하기 위한 두 가지 방법이 있습니다.하나는 모든 열의 이름을 테이블의 접두사로 바꾸는 것입니다.저는 이것을 여러 번 보았지만, 정말 마음에 들지 않습니다.중복되고 많은 타이핑이 발생하며 출처가 불분명한 열 이름의 경우에는 항상 별칭을 사용할 수 있습니다.

이 작업을 끝까지 수행할 경우에는 테이블 이름의 별칭을 지정하는 각 테이블에 대한 보기를 작성하는 것이 좋습니다.그런 다음 테이블 대신 해당 뷰에 대해 참여합니다.이렇게 하면 *(원하는 경우)를 자유롭게 사용할 수 있고, 원하는 경우 원본 열 이름을 가진 테이블을 자유롭게 사용할 수 있으며, 보기에서 이름 변경 작업을 이미 수행했기 때문에 이후 쿼리를 쉽게 작성할 수 있습니다.

마지막으로, 각 열이 어떤 테이블에서 왔는지 알아야 하는 이유가 명확하지 않습니다.이것이 중요합니까?궁극적으로 중요한 것은 그들이 포함하고 있는 데이터입니다.UserID가 User 테이블에서 나왔는지 UserQuestion 테이블에서 나왔는지는 중요하지 않습니다.물론 업데이트가 필요한 시점은 중요하지만, 그 시점에서는 이미 스키마를 잘 알고 있어야 결정할 수 있습니다.

스키마 변경이 필요한 경우 다음과 같이 수행할 수 있습니다. 1.관련된 모든 테이블에 대해 'DESCRIBE table' 쿼리를 실행합니다. 2.반환된 필드 이름을 사용하여 선택한 별칭으로 접두사가 붙은 열 이름 문자열을 동적으로 구성할 수 있습니다.

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 필드가 있을 때 다중 테이블 조인의 각 테이블을 독립적으로 업데이트할 수 있는 방식으로 이 정확한 데이터를 사용하는 것으로 나타났습니다.

별칭 없이는 이 작업을 수행할 수 없습니다. 단순히 가입하는 테이블 2개 또는 3개에 해당 필드가 있는 경우 where 절의 필드를 어떻게 참조하시겠습니까?당신이 어떤 것을 참조하려고 하는지 mysql에 대해서는 불분명할 것입니다.

솔루션을 발전시킨 후, 저는 다음과 같이 문제에 접근할 것입니다.

먼모든목만다듭니의 합니다.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.

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

나는 노드에서 더미 또는 보초 열을 사용하는 것을 제안하는 답변을 기반으로 솔루션을 구현했습니다.다음과 같은 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)
  })
})

제가 하는 일은 Excel을 사용하여 절차를 연결하는 것입니다.예를 들어, 먼저 *를 선택하고 모든 열을 Excel에 붙여넣습니다.그러면 기둥을 둘러싸는 데 필요한 코드를 작성해 주세요.예를 들어, 나는 많은 칼럼들에 적응할 필요가 있었습니다.a열에 필드를, b열에 "as prev_"를, c열에 필드를 다시 입력합니다.열 d에는 열이 있습니다.

그런 다음 열 e에 탄산염을 사용하고 공백을 포함하여 함께 병합합니다.그런 다음 이것을 잘라내어 SQL 코드에 붙여넣습니다.또한 이 방법을 사용하여 수백 개의 필드 테이블에서 각 필드에 대해 수행해야 하는 동일한 필드 및 기타 더 긴 코드에 대한 대소문자를 작성했습니다.

지정된 접두사를 사용하여 필드 목록을 만듭니다.

select
    name + ' as prefix.' + name + ','
from sys.columns where object_id = object_id('mytable')
order by column_id

매우 우수한 'PHP(Wordpress) 기능'과 동일한 반응을 보이지만 케이크용으로 코딩되어 있습니다.PHP 4.3. 배치 위치src/Controller/Component/MyUtilsComponent.php

<?php

namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Datasource\ConnectionManager;

class MyUtilsComponent extends Component
{
    public static function prefixedTableFieldsWildcard(string $table, string $alias, string $connexion = 'default'): string
    {
        $c = ConnectionManager::get($connexion);
        $columns = $c->execute("SHOW COLUMNS FROM $table");
        $field_names = [];
        foreach ($columns as $column) {
            $field_names[] = $column['Field'];
        }

        $prefixed = [];
        foreach ($field_names as $field_name) {
            $prefixed[] = "`{$alias}`.`{$field_name}` AS `{$alias}.{$field_name}`";
        }
        return implode(', ', $prefixed);
    }
}

테스트 및 사용

    function testPrefixedTableFieldsWildcard(): void
    {
        $fields = MyUtilsComponent::prefixedTableFieldsWildcard('metas', 'u', 'test');
        $this->assertEquals('`u`.`id` AS `u.id`, `u`.`meta_key` AS `u.meta_key`, `u`.`meta_value` AS `u.meta_value`, `u`.`meta_default` AS `u.meta_default`, `u`.`meta_desc` AS `u.meta_desc`', $fields,);
    }

여러분은 마이크로소프트가 13년 동안 이것을 도입했을 것이라고 생각할 것입니다.디버깅 목적으로 매우 유용할 것입니다.제가 습관적으로 하는 것은 비교하고 싶은 열을 선택하고 마지막에 *를 붙여 제가 보고 싶은 다른 항목을 잡는 것입니다.

동물로부터 a.breed, a.size, p.breed, p.size, a., p.size를 선택합니다. p.breed=p.breed.

어쨌든 당신은 아이디어를 얻습니다.

언급URL : https://stackoverflow.com/questions/329931/sql-select-join-is-it-possible-to-prefix-all-columns-as-prefix

반응형