MySQL Удалить символы из заголовков столбцов

Все мои заголовки столбцов в базе данных MySQL имеют префикс числа, 1_X, 2_X и т. д., что делает невозможным перенос данных в IDL с помощью простого оператора select для ввода всей таблицы. Я не уверен, но я вижу два возможных пути:

1) Принесите таблицу с псевдонимами имен столбцов. Могу ли я использовать TRIM или SUBSTRING_INDEX для удаления/замены первых двух символов?

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

Если бы не было так много разных таблиц (все с 1_X, 2_X и т. д.), не было бы проблем с выбором вручную 1_X AS X, но это невозможно. Было бы здорово иметь возможность использовать TRIM/SUBSTRING для заголовков столбцов в операторе select.

Спасибо.


person user3306708    schedule 27.03.2014    source источник


Ответы (3)


Невозможно использовать функции в операторе SQL для изменения идентификатора, присвоенного возвращаемому столбцу. Способ SQL для указания идентификатора столбца в наборе результатов заключается в использовании подхода expr AS alias.


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

Вы можете просто использовать оператор SQL для создания списка SELECT для вас.

(ПРИМЕЧАНИЕ: функция GROUP_CONCAT ограничена некоторыми системными/сессионными переменными: group_concat_max_len и max_allowed_packet, их достаточно легко настроить выше, хотя изменение глобального max_allowed_packet может потребовать перезапуска MySQL.)

Чтобы вернуть список SELECT во всей одной строке (при условии, что вы не перейдете пределы GROUP_CONCAT), что-то вроде:

SELECT c.table_schema
     , c.table_name
     , GROUP_CONCAT(
          CONCAT('t.`',c.column_name,'` AS `x',c.column_name,'`')
          ORDER BY c.ordinal_position
       ) AS select_list_expr
  FROM information_schema.columns c
  FROM information_schema.columns c
 WHERE c.table_schema = 'mydatabase'
 GROUP BY c.table_schema, c.table_name

Или вы могли бы даже вернуть весь оператор SELECT, если вы завернули это GROUP_CONCAT выражение (которое создает список выбора) в другое CONCAT

Что-то вроде этого:

SELECT CONCAT('SELECT '
          , GROUP_CONCAT(
               <select_list_expr>
            )
          , ' FROM `',c.table_schema,'`.`',c.table_name,'` t;'
       ) AS stmt
  FROM information_schema.columns c
 WHERE c.table_schema = 'mydatabase'
 GROUP BY c.table_schema, c.table_name

Вы можете использовать более умное выражение для <select_list_expr>, чтобы проверить наличие начальных «цифровых» символов и назначить псевдоним только тем столбцам, которые в нем нуждаются, и оставить другие столбцы без изменений, хотя это снова создает возможность возврата повторяющихся имен столбцов.

То есть, если у вас уже есть столбцы с именами '1_X' и 'x1_X' в одной таблице. Но тщательно подобранный главный герой может избежать этой проблемы...

<select_list_expr> мог бы быть более умным, выполнив условный тест для начального символа цифры, что-то вроде этого:

SELECT CONCAT('SELECT '
          , GROUP_CONCAT(
               CASE
               WHEN c.column_name REGEXP '^[[:digit:]]'
               THEN CONCAT('t.`',c.column_name,'` AS `x',c.column_name,'`')
               ELSE CONCAT('t.`',c.column_name,'`')
               END
           )
          , ' FROM `',c.table_schema,'`.`',c.table_name,'` t;'
       ) AS stmt
  FROM information_schema.columns c
 WHERE c.table_schema = 'mydatabase'
 GROUP BY c.table_schema, c.table_name

Опять же, при таком подходе существует вероятность создания «дубликатов» имен столбцов. Условный тест «c.column_name REGEXP» может быть расширен для проверки других «недопустимых» начальных символов.


В качестве примечания: в какой-то момент кто-то подумал, что «хорошей идеей» будет именовать столбцы с помощью начальных цифр. То, что что-то разрешено, не означает, что это хорошая идея.


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

person spencer7593    schedule 27.03.2014
comment
prepending также будет работать нормально, это выглядит многообещающе, и я не могу дождаться, чтобы приступить к работе над этим. программа, которую я использую для передачи данных CSV в базу данных mysql, использует этот формат в течение многих лет, и теперь у меня есть много тысяч столбцов с начальными цифрами, которым не видно конца. я дважды проверю, чтобы ввести обратные кавычки. - person user3306708; 28.03.2014
comment
Я пытаюсь понять это самостоятельно, но у меня проблемы, так как я также пытаюсь узнать больше о CONCAT. Это работает почти идеально, но я не могу выполнить этот запрос для отдельной таблицы. - person user3306708; 28.03.2014
comment
Вы можете добавить просто `AND c.table_name = 'mytablename'`. Я не уверен, что понял, этот запрос не выполняется для какой-либо конкретной таблицы, он просто создает оператор SQL, который будет извлекать строки из таблицы. Производимый им оператор SELECT можно использовать как часть оператора CREATE VIEW, но я не рекомендовал (и не рекомендую) этого, потому что вы не хотите вводить представления, снижающие производительность, в вашу схему MySQL. - person spencer7593; 28.03.2014
comment
Я предполагаю, что по какой-то причине вы не можете изменить имена существующих столбцов с помощью операторов ALTER TABLE (т. е. уже запущена куча SQL, которая использует существующие имена столбцов, и это сломается), и по какой-то причине ваш IDL запрещает заключать имена столбцов в обратные кавычки или запрещать режим кавычек ANSI и заключать имена столбцов в двойные кавычки. (Запрос в моем ответе просто демонстрирует, как извлечь имена столбцов для таблицы и использовать строковые функции, чтобы преобразовать их во что-то, что вы можете использовать. - person spencer7593; 28.03.2014

Я думаю, вы можете следовать варианту 2. Однако это не будет быстрым решением.

Другой способ обойти это может быть,

  1. Создайте сценарий схемы для таблиц, которые вы хотите исправить.
  2. Откройте скрипт в notepad++ или любом редакторе, который поддерживает поиск с использованием регулярных выражений.
  3. Найдите и замените выражением [0-9]+_ и пустой строкой для замены.
  4. Создайте новые таблицы с помощью этого скрипта и скопируйте в них данные.

Это может показаться ручным подходом, но вы сделаете это один раз для всех ваших таблиц.

person Riz    schedule 27.03.2014
comment
Существует возможность создания повторяющихся (или даже нулевой длины) имен столбцов с удалением начальных цифр. - person spencer7593; 28.03.2014
comment
Это было бы здорово, прямолинейно и легко, но мне нужно, чтобы это работало в команде sql, поскольку новые таблицы создаются с начальными числами регулярно (не часто, но достаточно). Мне нужно, чтобы это было максимально автоматизировано, если меня не будет рядом, чтобы помочь в будущем. - person user3306708; 28.03.2014

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

Сначала получите имена столбцов:

show columns from tbl_client;
+-------------------------------+-----------------------------------+------+-----+---------------------+-----------------------------+
| Field                         | Type                              | Null | Key | Default             | Extra                       |
+-------------------------------+-----------------------------------+------+-----+---------------------+-----------------------------+
| 1_X                           | int(11)                           | NO   | PRI | NULL                | auto_increment              |

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

Затем создайте новый выбор

SELECT 1_X as NEW_COLUMN_NAME_FOR_FIELD_1 FROM tbl_client;
person crafter    schedule 27.03.2014