SQL select join: возможно ли префикс всех столбцов как 'prefix. *'?

Мне интересно, возможно ли это в 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_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 * для двух таблиц с объединением и уметь определять по именам столбцов, которые я получаю в моем наборе результатов, какие столбцы взяты из таблицы A, а какие - из таблицы B. Опять же, я не хочу перечислять столбцы по отдельности, мне нужно уметь делать SELECT *.

Какого именно результата вы ожидаете от вашего запроса? я запутался

GregD 01.12.2008 06:18

GregD: Я хочу, чтобы все имена столбцов, получаемые из b. *, Были предварены некоторой константой, которую я указываю. Например, вместо «name» и «number» я хочу указать, скажем, префикс «special_» и получить «special_name» и «special_number». Но я не хочу делать это для каждого столбца отдельно.

foxdonut 01.12.2008 06:31

Когда я делаю быстрый SELECT, чтобы увидеть столбцы из нескольких таблиц, я иногда делаю SELECT 'AAAAA', A. *, 'BBBBB', B. * FROM TableA AS A JOIN TableB AS B ON A.ID = B.ID, чтобы я хотя бы иметь идентификатор таблицы при сканировании по строкам

Kristen 24.02.2009 17:42

Возможный дубликат: stackoverflow.com/questions/2595068/…

Andrioid 04.09.2010 11:17
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
227
4
169 521
23
Перейти к ответу Данный вопрос помечен как решенный

Ответы 23

Различные продукты баз данных дадут вам разные ответы; но вы настраиваете себя на обиду, если зайдете так далеко. Намного лучше выбрать нужные столбцы и дать им свои собственные псевдонимы, чтобы идентичность каждого столбца была кристально ясной, и вы могли различать их в результатах.

Точка зрения принята, но моя цель здесь - что-то очень общее, поэтому неявка не является проблемой. Фактически, необходимость быть конкретным бы может быть проблемой.

foxdonut 01.12.2008 06:33

См. Дальнейшее представление ниже. Можно использовать dot.notation, что, вероятно, вы получите по умолчанию?

dkretz 01.12.2008 06:43

Это важно для удобочитаемости. Я надеялся сделать это прямо сейчас, потому что у меня есть проверенный процесс CTE. бывший. CTE_A -> CTE_B -> CTE_C -> CTE_D -> select / insert Нет необходимости указывать столбцы, которые мне нужны, пока окончательный оператор выбора и производительность не будут рассматриваться.

ThomasRones 28.05.2019 17:46

select * обычно приводит к плохому коду, так как новые столбцы, как правило, добавляются или порядок столбцов меняется в таблицах довольно часто, что обычно очень тонко нарушает select *. Так что перечисление столбцов - правильное решение.

Что касается того, как выполнить ваш запрос, не уверен в mysql, но в sqlserver вы можете выбрать имена столбцов из syscolumns и динамически построить предложение select.

Точка принята, но в моем контексте мне нужно что-то общее и динамическое, поэтому на самом деле мой код будет адаптироваться к добавлению / изменению порядка новых столбцов и т. д. Я не хочу перечислять столбцы по отдельности.

foxdonut 01.12.2008 06:34

Выбор из syscolumns для динамического построения оператора select - ужасный взлом, и я бы не рекомендовал его в производственной среде.

Juliet 01.12.2008 08:07

Единственная известная мне база данных, которая делает это, - это SQLite, в зависимости от настроек, которые вы настроили с помощью PRAGMA full_column_names и PRAGMA short_column_names. См. http://www.sqlite.org/pragma.html

В противном случае все, что я могу порекомендовать, - это выбирать столбцы в результирующем наборе по порядковому номеру, а не по имени столбца, если вам слишком сложно вводить имена столбцов в запросе.

Это хороший пример того, почему использование SELECT * - плохая практика - потому что в конечном итоге вам все равно придется вводить все имена столбцов.

Я понимаю необходимость поддержки столбцов, которые могут изменять имя или положение, но использование подстановочных знаков делает Сильнее не проще.

Обратите внимание, что и full_column_names, и short_column_names являются устарел в SQLite.

isanae 29.05.2016 19:52
Ответ принят как подходящий

Я вижу здесь две возможные ситуации. Во-первых, вы хотите знать, существует ли для этого стандарт SQL, который можно использовать в целом независимо от базы данных. Нет, нет. Во-вторых, вы хотите знать о конкретном продукте dbms. Тогда вам нужно его идентифицировать. Но я полагаю, что наиболее вероятным ответом будет то, что вы получите что-то вроде «a.id, b.id», поскольку именно так вам нужно будет идентифицировать столбцы в вашем выражении SQL. И самый простой способ узнать, что такое значение по умолчанию, - это просто отправить такой запрос и посмотреть, что вы получите в ответ. Если вы хотите указать, какой префикс стоит перед точкой, вы можете, например, использовать "SELECT * FROM a AS my_alias".

Я не уверен, как это отвечает на ваш вопрос. Я использую MS SQL Server и добавляю псевдоним после имени таблицы, не добавляя псевдоним к именам столбцов в наборе результатов.

paiego 04.11.2015 23:18

Я могу придумать два способа сделать это многоразовым. Один из них - переименовать все ваши столбцы с префиксом таблицы, из которой они взяты. Я видел это много раз, но мне это очень не нравится. Я считаю, что это избыточно, требует много ввода, и вы всегда можете использовать псевдонимы, когда вам нужно охватить случай, когда имя столбца имеет неясное происхождение.

Другой способ, который я бы порекомендовал вам сделать в вашей ситуации, если вы стремитесь увидеть это до конца, - это создать представления для каждой таблицы, которые являются псевдонимами имен таблиц. Затем вы присоединяетесь к этим представлениям, а не к таблицам. Таким образом, вы можете свободно использовать *, если хотите, свободно использовать исходные таблицы с исходными именами столбцов, если хотите, а также упрощает написание любых последующих запросов, потому что вы уже выполнили работу по переименованию в представлениях.

Наконец, мне непонятно, почему вам нужно знать, из какой таблицы был взят каждый из столбцов. Это имеет значение? В конечном итоге важны данные, которые они содержат. Пришел ли UserID из таблицы User или из таблицы UserQuestion, на самом деле не имеет значения. Конечно, имеет значение, когда вам нужно ее обновить, но к этому моменту вы уже должны знать свою схему достаточно хорошо, чтобы это определить.

«Наконец, я не понимаю, почему вам нужно знать, из какой таблицы был взят каждый из столбцов. Имеет ли это значение?» <- 11 лет спустя одним из вариантов использования является сканирование структур в Go.

Lee Benson 15.02.2019 13:52

Для этого не существует стандарта 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 01.12.2008 08:58

Кейд: Спасибо за информацию, это интересно. К сожалению, создание / изменение базы данных в моем случае не вариант. Devtron: если вы пытаетесь сопоставить информацию, полученную в результате запроса, с различными свойствами объекта, эта информация становится очень полезной.

foxdonut 01.12.2008 11:44

Иногда имена столбцов в разных таблицах совпадают, но не содержат одинаковых значений. Следовательно, необходимо добавить к ним префикс, чтобы различать их в представлениях или производных таблицах (которые должны иметь все уникальные имена столбцов).

Cade Roux 01.12.2008 22:33

@Frederic, ваш код должен где-то жить - он просто генерирует код. Опять же, это можно сделать один раз во время разработки или динамически во время выполнения.

Cade Roux 01.12.2008 22:35

Я нахожусь в той же лодке, что и OP - у меня есть десятки полей из трех разных таблиц, к которым я присоединяюсь, некоторые из которых имеют то же имя (например, id, name и т. д.). Я не хочу перечислять каждое поле, поэтому моим решением было присвоить псевдоним тем полям, которые имеют общее имя, и использовать select * для тех, у которых есть уникальное имя.

Например :

таблица а: я бы, имя, поле1, поле2 ...

таблица b: я бы, имя, поле3, поле4 ...

выберите a.id как aID, a.name как aName, a. *, b.id как bID, b.name как bName, b. * .....

При доступе к результатам я использую псевдонимы для этих полей и игнорирую «исходные» имена.

Возможно, это не лучшее решение, но оно работает для меня .... я использую mysql

Или вы можете использовать Red Gate SQL Refactor или SQL Prompt, которые расширяют ваш SELECT * в списки столбцов одним нажатием кнопки Tab.

поэтому в вашем случае, если вы введете SELECT * FROM A JOIN B ... Перейти в конец *, кнопка Tab, вуаля! вот увидишь ВЫБЕРИТЕ A.column1, A.column2, ...., B.column1, B.column2 ИЗ A JOIN B

Хотя это не бесплатно

Если вы беспокоитесь об изменении схемы, это может сработать для вас: 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 */

Обратите внимание на поля: каталог, таблица, org_name

Теперь вы знаете, какие поля в вашем SQL принадлежат какой схеме (или каталогу) и таблице. Этого достаточно, чтобы в целом идентифицировать каждое поле из многотабличного sql-запроса без необходимости использовать псевдоним.

Фактический продукт SqlYOG демонстрирует использование этих точных данных в такой усадьбе, что они могут независимо обновлять каждую таблицу соединения нескольких таблиц, когда присутствуют поля PK.

Невозможно сделать это без псевдонима просто потому, что как вы собираетесь ссылаться на поле в предложении where, если это поле существует в 2 или 3 таблицах, к которым вы присоединяетесь? Для mysql будет непонятно, на какой из них вы пытаетесь ссылаться.

Я полностью понимаю, почему это необходимо - по крайней мере, для меня это удобно во время быстрого прототипирования, когда необходимо объединить множество таблиц, включая множество внутренних соединений. Как только имя столбца во втором подстановочном знаке поля «jointable. *» Совпадает, значения полей основной таблицы заменяются значениями jointable. Склонность к ошибкам, разочарование и нарушение 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
        )
)

этот пост немного устарел, но функциональный подход определенно элегантен и хорошо работает.

glihm 24.07.2020 06:06

Кажется, что ответ на ваш вопрос отрицательный, однако вы можете использовать один прием - назначить фиктивный столбец для разделения каждой новой таблицы. Это особенно хорошо работает, если вы просматриваете набор результатов для списка столбцов на языке сценариев, таком как 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

Я понимаю, что это не совсем ответ на ваш вопрос, но если вы программист, это отличный способ разделить таблицы с повторяющимися именами столбцов. Надеюсь, это кому-то поможет.

Мне это действительно помогает. Большое спасибо за то, что поделились

Chidiebere 10.09.2020 12:54

Я полностью понимаю вашу проблему с повторяющимися именами полей.

Мне это тоже было нужно, пока я не закодировал свою собственную функцию для ее решения. Если вы используете 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. Сценарий можно найти повсюду, например, преобразование базы данных, миграция, администрирование и т. д. Большинство этих 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;

Исходя из это решение, я бы подошел к проблеме следующим образом:

Сначала создайте список всех операторов 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. Но этот код не совсем работает в SQL Server, потому что ИСПОЛЬЗОВАНИЕ не поддерживается.

Прокомментируйте, можете ли вы проверить / исправить этот код, например, MySQL.

Я решил аналогичную проблему, переименовав поля в соответствующих таблицах. Да, у меня была привилегия сделать это, и я понимаю, что это может не у всех. Я добавил префикс к каждому полю в таблице, представляющей имя таблицы. Таким образом, SQL, отправленный OP, останется неизменным -

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

и по-прежнему давать ожидаемые результаты - простоту определения, к какой таблице принадлежат поля вывода.

Недавно столкнулся с этой проблемой в NodeJS и Postgres.

ES6 подход

Я не знаю никаких известных мне функций СУБД, которые обеспечивали бы эту функциональность, поэтому я создал объект, содержащий все мои поля, например:

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.info('SELECT ' + columns_joined.join(',') + ' FROM tab1, tab2 WHERE tab1.id = tab2.id');

Ни за что! Это какая-то хитрая SQL-инъекция, которая не работает с выражениями.

ratijas 18.02.2020 19:06

PHP 7.2 + MySQL / Мариадб

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, возвращенного моим драйвером, но должно быть легко изменить для других драйверов БД):

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 и «as prev_» в столбце B, а мои поля снова в столбце c. В столбце d у меня будет столбец.

Затем используйте concatanate в столбце e и объедините их вместе, не забудьте включить пробелы. Затем вырежьте и вставьте это в свой sql-код. Я также использовал этот метод для создания операторов case для одного и того же поля и других более длинных кодов, которые мне нужно сделать для каждого поля в таблице из нескольких сотен полей.

В postgres я использую функции json, чтобы вместо этого возвращать объекты json .... затем, после запроса, я json_decode поля с суффиксом _json.

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_decode () их, если они имеют суффикс «_json» (также удаляя суффикс. В конце концов, я получаю объект с именем «tab1», который включает все поля tab1 и еще одно, называемое «tab2», которое включает все поля tab2.

Это создает список полей с заданным префиксом

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

Другие вопросы по теме