MySQL, Перевірте, чи існує стовпець у таблиці з SQL


130

Я намагаюся написати запит, який перевірить, чи є конкретна таблиця в MySQL конкретний стовпець, а якщо ні - створіть її. Інакше нічого не робити. Це дійсно проста процедура в будь-якій базі даних корпоративного класу, але, здається, MySQL є винятком.

Я думав щось подібне

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
           WHERE TABLE_NAME='prefix_topic' AND column_name='topic_last_update') 
BEGIN 
ALTER TABLE `prefix_topic` ADD `topic_last_update` DATETIME NOT NULL;
UPDATE `prefix_topic` SET `topic_last_update` = `topic_date_add`;
END;

працювало б, але це погано виходить з ладу. Чи є спосіб?



Чому б просто не створити його? Якщо воно існує, створення не вийде, але вам все одно.
Брайан Хупер

створення відбувається всередині транзакції, і невдача припинить всю транзакцію, сумно, але правда
завершується

@haim - thans для заголовків, але запит, запропонований у вашому посиланні, працює лише в межах процедури :(
закривається

2
Виписки DDL викликають неявну фіксацію в поточній транзакції. dev.mysql.com/doc/refman/5.0/uk/implicit-commit.html
Mchl

Відповіді:


259

Це добре працює для мене.

SHOW COLUMNS FROM `table` LIKE 'fieldname';

З PHP це було б щось на зразок ...

$result = mysql_query("SHOW COLUMNS FROM `table` LIKE 'fieldname'");
$exists = (mysql_num_rows($result))?TRUE:FALSE;

8
Питання не в тому, як це зробити за допомогою php + sql або java + sql, а в тому, як це зробити за допомогою чистого sql / mysql, звідси і downvote
Юрій Наконечний,

61
Ви відповідаєте на запитання + деяка інформація, яка допомогла мені та, ймовірно, іншим, +1
Francisco Presencia

@Mfoo Спасибі Mfoo, ти врятував мені день! Працює як шарм. Одне з найкращих рішень, крім створення процедур для цього завдання.
веббловер

8
Юра: Чистий відповідь SQL / MySQL є першою частиною, де він каже, що використовується "ПОКАЖИТИ КОЛИНИ З таблиці LIKE" Ім'я поля "". Ви можете нехтувати PHP-кодом, це лише приклад одного із способів отримання та інтерпретації результату, якщо ви випадково використовуєте PHP.
orrd

1
@codenamezero Я припускаю, що ви маєте на увазі використання MSSQL, це питання стосувалося MySQL. зверніться до цієї публікації для MSSQL
Mfoo

158

@julio

Дякуємо за приклад SQL. Я спробував запит, і я думаю, що для правильної роботи він потребує невеликих змін.

SELECT * 
FROM information_schema.COLUMNS 
WHERE 
    TABLE_SCHEMA = 'db_name' 
AND TABLE_NAME = 'table_name' 
AND COLUMN_NAME = 'column_name'

Це працювало для мене.

Дякую!


З мого обмеженого дослідження випливає, що не у всіх хостинг-середовищах є БД information_schema. Усі середовища cpanel, якими я користувався, мають його. Це надане рішення залежить від існуючої цієї БД.
cardi777

2
Ця відповідь краще, ніж використання "SHOW COLUMNS", оскільки вона використовує стандартний спосіб отримання ANSI таблиці, на відміну від SHOW COLUMNS, який характерний для MySQL. Тож це рішення працюватиме з іншими базами даних. Використання "information_schema" здається дивним, і ви можете подумати, що це був би не стандартний спосіб SQL, але це так.
orrd

5
Зауважте, що ця відповідь отримує лише інформацію про існування стовпця. Якщо ви хочете умовно виконати деякі оператори DDL, вам доведеться завершити все в процедурі, яка дозволяє такі оператори IFтощо. Див. Stackoverflow.com/questions/7384711/… для прикладу, як обернути процедуру тест для стовпця та умовного оператора DML.
Крістофер Шульц

@Iain: stackoverflow.com/questions/32962149 / ... Я refered ваш відповідь
Амар Сінгх

Це приємніше, ніж підхід "SHOW COLUMNS" нижче, як це можна використовувати в параметризованих запитах, що знижують ризик ін'єкції SQL. Просто хотів додати, ви можете використовувати функцію DATABASE () для заповнення стовпця TABLE_SCHEMA.
Андрій

16

Щоб допомогти кожному, хто шукає конкретний приклад того, що описав @Mchl, спробуйте щось подібне

SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'

Якщо він повертає помилкові (нульові результати), знаєте, що стовпець не існує.


2
Я вважаю, що так має бути TABLE_NAME = 'my_table', TABLE_SCHEMA - схема, в якій знаходиться таблиця. ТобтоSELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'my_schema' AND TABLE_NAME = 'my_table' AND COLUMN_NAME = 'my_column'
AaronHolland

10

Далі йде ще один спосіб зробити це за допомогою звичайного PHP без бази даних information_schema:

$chkcol = mysql_query("SELECT * FROM `my_table_name` LIMIT 1");
$mycol = mysql_fetch_array($chkcol);
if(!isset($mycol['my_new_column']))
  mysql_query("ALTER TABLE `my_table_name` ADD `my_new_column` BOOL NOT NULL DEFAULT '0'");

Чому ви хочете уникати використання information_schema? Він існує саме для цієї мети. (Також ця тема досить стара і на неї вже відповіли.)
Лей,

1
У моїх тестах це приблизно на 10-50 разів швидше, ніж використання інформаційної схеми. Це вимагає, щоб у таблиці був принаймні один рядок, що ви не завжди можете гарантувати.
Martijn

isset()Якщо ключ масиву існує, але значення " NULL " буде "невірним" . Краще використовувати на array_key_exists()зразокif( !array_key_exists( 'my_new_column', $mycol ) )
Пол Гейслер

1
Ця відповідь зробила мене обличчям, бо я не помітив простої isset()перевірки. Це не вирішує питання, але краще, якщо вам вже потрібно виконати запит вибору і мати результат у пам'яті.
Сифон

10

Я кинув цю збережену процедуру разом із початком коментарів @ lain вище, начебто добре, якщо вам потрібно зателефонувати більше ніж кілька разів (і не потрібен php):

delimiter //
-- ------------------------------------------------------------
-- Use the inforamtion_schema to tell if a field exists.
-- Optional param dbName, defaults to current database
-- ------------------------------------------------------------
CREATE PROCEDURE fieldExists (
OUT _exists BOOLEAN,      -- return value
IN tableName CHAR(255),   -- name of table to look for
IN columnName CHAR(255),  -- name of column to look for
IN dbName CHAR(255)       -- optional specific db
) BEGIN
-- try to lookup db if none provided
SET @_dbName := IF(dbName IS NULL, database(), dbName);

IF CHAR_LENGTH(@_dbName) = 0
THEN -- no specific or current db to check against
  SELECT FALSE INTO _exists;
ELSE -- we have a db to work with
  SELECT IF(count(*) > 0, TRUE, FALSE) INTO _exists
  FROM information_schema.COLUMNS c
  WHERE 
  c.TABLE_SCHEMA    = @_dbName
  AND c.TABLE_NAME  = tableName
  AND c.COLUMN_NAME = columnName;
END IF;
END //
delimiter ;

Працювати з fieldExists

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_option', NULL) //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> call fieldExists(@_exists, 'jos_vm_product', 'child_options', 'etrophies') //
Query OK, 0 rows affected (0.01 sec)

mysql> select @_exists //
+----------+
| @_exists |
+----------+
|        1 |
+----------+

MIster @quickshiftin, велике спасибі Це допомагає мені перевірити, чи є таблиця закінчується , перевіряючи, чи є ExpirationDateполе. 😊
Жанкарло Фонталво

@JeancarloFontalvo Моє задоволення! Також перевірка мої MySQL-контролери проекту я почав для перевірки схеми з більш високими методами рівня.
швидкий перехід

1
OMG Це як бібліотека 😱. Дякуємо, що поділилися цим паном!
Жанкарло Фонталво

8

Виберіть просто інформаційне ім'я стовпця з інформаційної схеми і поставте результат цього запиту в змінну. Потім випробуйте змінну, щоб визначити, чи потрібна зміна таблиці чи ні.

PS Не забудьте вказати і TABLE_SCHEMA для таблиці COLUMNS.


1
Я досить новачок у MySQL, чи можете ви тут розмістити невеликий приклад?
завершення

2

Я використовую цей простий сценарій:

mysql_query("select $column from $table") or mysql_query("alter table $table add $column varchar (20)");

Він працює, якщо ви вже підключені до бази даних.


Це спрацювало б лише в тому випадку, якщо в таблиці також були рядки даних. Але якби стіл був порожній, це не працювало б.
orrd

1
не ідеально, використовує старі драйвери, не працює, якщо таблиця порожня, вводи не вийшли, але мені подобається, як ви це зробили в одному рядку. +1
Я боровся ведмедя один раз.

1

Велике спасибі Mfoo, який поставив дійсно приємний сценарій для динамічного додавання стовпців, якщо його немає в таблиці. Я покращив його відповідь за допомогою PHP . Сценарій додатково допоможе знайти скільки таблиць на насправді необхідний «Додати стовпець» MySQL COMAND. Просто спробуйте рецепт. Працює як шарм.

<?php
ini_set('max_execution_time', 0);

$host = 'localhost';
$username = 'root';
$password = '';
$database = 'books';

$con = mysqli_connect($host, $username, $password);
if(!$con) { echo "Cannot connect to the database ";die();}
mysqli_select_db($con, $database);
$result=mysqli_query($con, 'show tables');
$tableArray = array();
while($tables = mysqli_fetch_row($result)) 
{
     $tableArray[] = $tables[0];    
}

$already = 0;
$new = 0;
for($rs = 0; $rs < count($tableArray); $rs++)
{
    $exists = FALSE;

    $result = mysqli_query($con, "SHOW COLUMNS FROM ".$tableArray[$rs]." LIKE 'tags'");
    $exists = (mysqli_num_rows($result))?TRUE:FALSE;

    if($exists == FALSE)
    {
        mysqli_query($con, "ALTER TABLE ".$tableArray[$rs]." ADD COLUMN tags VARCHAR(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL");
        ++$new;
        echo '#'.$new.' Table DONE!<br/>';
    }
    else
    {
        ++$already;
        echo '#'.$already.' Field defined alrady!<br/>';    
    }
    echo '<br/>';
}
?>

1

Ця робота для мене із зразком PDO:

public function GetTableColumn() {      
$query  = $this->db->prepare("SHOW COLUMNS FROM `what_table` LIKE 'what_column'");  
try{            
    $query->execute();                                          
    if($query->fetchColumn()) { return 1; }else{ return 0; }
    }catch(PDOException $e){die($e->getMessage());}     
}

0

НЕ кладіть ALTER TABLE / MODIFY COLS або будь-які інші подібні операції з модифікацією таблиці всередині TRANSACTION. Трансакції призначені для того, щоб можна було відмовити ЗАПИТУВАННЯ помилки, а не для АЛЬТЕРАЦІЙ ... вона буде помилятися кожного разу в транзакції.

Просто запустіть запит SELECT * на столі та перевірте, чи стовпець стовпчик ...


ALTER(і подібний DDL) в MySQL дійсно здійснюють (неявно) транзакцію. Але використання SELECT * генерує великі накладні витрати в мережі для просто перевірки існування стовпця. Ви можете замість цього спробувати SELECT my_col_to_check FROM t LIMIT 0: якщо mysql генерує помилку, то стовпець, ймовірно, не існує (все-таки перевірте помилку, оскільки це може бути проблема з мережею чи інше!); якщо він не створює помилок, то стовпець існує. Я не впевнений, що це найкращий спосіб перевірити наявність колон.
Xenos
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.