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;

จะใช้งานได้ แต่ล้มเหลวอย่างรุนแรง มีวิธีหรือไม่?



ทำไมไม่เพียงสร้างมันขึ้นมา? ถ้ามีอยู่การสร้างจะล้มเหลว แต่คุณไม่สนใจ
Brian Hooper

การสร้างเกิดขึ้นในการทำธุรกรรมและความล้มเหลวจะยุติการทำธุรกรรมทั้งหมดเศร้า แต่เป็นจริง
clops

@haim - ใช้แทน Headup ได้ แต่คำค้นหาที่แนะนำในลิงค์ของคุณใช้ได้เฉพาะในขั้นตอนเท่านั้น :(
clops

2
คำสั่ง DDL ทำให้เกิดการกระทำโดยนัยในการทำธุรกรรมปัจจุบัน dev.mysql.com/doc/refman/5.0/en/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 มันเป็นวิธีการทำโดยใช้ pure sql / mysql ดังนั้น downvote
Yuriy Nakonechnyy

61
คุณตอบคำถาม + ข้อมูลบางอย่างที่ช่วยฉันและคนอื่น ๆ +1
Francisco Presencia

@Mfoo ขอบคุณ Mfoo คุณบันทึกวันของฉัน! ทำงานเหมือนจับใจ หนึ่งในโซลูชั่นที่ดีที่สุดนอกเหนือจากการสร้างขั้นตอนสำหรับงานนี้
webblover

8
Yura: คำตอบ SQL / MySQL ล้วนเป็นส่วนแรกที่เขาบอกว่าใช้ "SHOW COLUMNS FROM จากตารางเช่น 'fieldname'" คุณสามารถเพิกเฉยต่อโค้ด 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'

ที่ทำงานให้ฉัน

ขอบคุณ!


ดูเหมือนว่าจากการวิจัยที่ จำกัด ของฉันที่ว่าสภาพแวดล้อมการโฮสต์ไม่ทั้งหมดมี data_schema DB สภาพแวดล้อม cpanel ทั้งหมดที่ฉันใช้มีอยู่ โซลูชันที่มีให้นี้ขึ้นอยู่กับฐานข้อมูลนี้ที่มีอยู่
cardi777

2
คำตอบนี้ดีกว่าการใช้ "SHOW COLUMNS" เพราะใช้วิธีมาตรฐาน ANSI เพื่อรับข้อมูลตารางซึ่งแตกต่างจาก SHOW COLUMNS ซึ่งเฉพาะเจาะจงกับ MySQL ดังนั้นวิธีนี้จะทำงานกับฐานข้อมูลอื่น ๆ การใช้ "information_schema" ฟังดูแปลกและคุณคิดว่าคงไม่เป็นวิธีมาตรฐานของ SQL ในการทำสิ่งนี้ แต่มันก็เป็นเช่นนั้น
orrd

5
โปรดทราบว่าคำตอบนี้จะทำให้คุณได้รับข้อมูลเกี่ยวกับการมีอยู่ของคอลัมน์เท่านั้น หากคุณต้องการดำเนินการตามเงื่อนไขคำสั่ง DDL บางส่วนคุณจะต้องห่อทุกอย่างในโพรซีเดอร์ที่อนุญาตให้ใช้คำสั่งเช่นIFฯลฯ ดูstackoverflow.com/questions/7384711/…สำหรับตัวอย่างของการห่อโพรเซสรอบ ๆ การทดสอบคอลัมน์และคำสั่ง DML แบบมีเงื่อนไข
Christopher Schultz

@Iain: stackoverflow.com/questions/32962149/…ฉันได้อ้างอิงคำตอบของคุณแล้ว
Amar Singh

นี่เป็นวิธีที่ดีกว่าวิธี "SHOW COLUMNS" ด้านล่างซึ่งสามารถใช้ในคิวรีแบบพารามิเตอร์เพื่อลดความเสี่ยงของการฉีด SQL ต้องการเพิ่มคุณสามารถใช้ฟังก์ชัน DATABASE () เพื่อเติมคอลัมน์ TABLE_SCHEMA
Andrew

16

เพียงเพื่อช่วยให้ทุกคนที่กำลังมองหาตัวอย่างที่ชัดเจนของสิ่งที่ @Mchl อธิบายให้ลองทำเช่นนั้น

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

ถ้ามันคืนค่า false (ผลลัพธ์เป็นศูนย์) แสดงว่าคุณไม่มีคอลัมน์อยู่


2
ฉันเชื่อว่าควรเป็นTABLE_NAME = 'my_table'TABLE_SCHEMA คือ schema ที่มีอยู่ในตาราง IeSELECT * 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 มันมีอยู่เพียงเพื่อจุดประสงค์นี้ (เช่นกันเธรดนี้ค่อนข้างเก่าและได้รับคำตอบแล้ว)
Leigh

1
ในการทดสอบของฉันนี่เร็วกว่าการใช้ data_schema ประมาณ 10-50 เท่า มันต้องการให้ตารางมีอย่างน้อยหนึ่งแถวซึ่งคุณไม่สามารถรับประกันได้เสมอ
Martijn

isset()จะ trow 'ผิด' ถ้าคีย์อาร์เรย์มีอยู่ แต่มีค่าเป็นโมฆะ จะดีกว่าที่จะใช้array_key_exists()เช่นif( !array_key_exists( 'my_new_column', $mycol ) )
Paul Geisler

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เขตข้อมูลหรือไม่ 😊
Jeancarlo Fontalvo

@JeancarloFontalvo ความสุขของฉัน! เช็คเอาต์โครงการผู้ตรวจสอบ mysqlของฉันฉันเริ่มตรวจสอบสคีมาด้วยวิธีการระดับสูงขึ้น
quickshiftin

1
OMG มันเหมือนห้องสมุด😱 ขอบคุณที่แชร์มิสเตอร์!
Jeancarlo Fontalvo

8

เลือกเพียง column_name จาก data schema และใส่ผลลัพธ์ของแบบสอบถามนี้ลงในตัวแปร จากนั้นทดสอบตัวแปรเพื่อตัดสินใจว่าตารางต้องการการเปลี่ยนแปลงหรือไม่

ป.ล. อย่าตัดทอนเพื่อระบุ TABLE_SCHEMA สำหรับตาราง COLUMNS เช่นกัน


1
ฉันค่อนข้างใหม่กับ MySQL คุณสามารถโพสต์ตัวอย่างเล็ก ๆ ที่นี่ได้ไหม
clops

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 หรือการดำเนินการ mod table อื่น ๆ ภายในการทำธุรกรรม ธุรกรรมที่สามารถย้อนกลับความล้มเหลวของ QUERY ไม่ใช่เพื่อการเปลี่ยนแปลง ... มันจะเกิดข้อผิดพลาดทุกครั้งในการทำธุรกรรม

เพียงเรียกใช้แบบสอบถาม SELECT * บนตารางและตรวจสอบว่ามีคอลัมน์ ...


ALTER(และ DDL เช่นนั้น) ใน MySQL แน่นอนการทำธุรกรรม (โดยนัย) การทำธุรกรรม แต่การใช้ SELECT * จะทำให้เกิดโอเวอร์เฮดขนาดใหญ่ในเครือข่ายเพียงตรวจสอบการมีอยู่ของคอลัมน์ คุณอาจลองSELECT my_col_to_check FROM t LIMIT 0: ถ้า mysql สร้างข้อผิดพลาดแล้วคอลัมน์อาจไม่มีอยู่ (ยังตรวจสอบข้อผิดพลาดเนื่องจากอาจเป็นปัญหาเครือข่ายหรืออะไรก็ตาม!); หากไม่มีข้อผิดพลาดจะมีคอลัมน์อยู่ ฉันไม่แน่ใจว่าเป็นวิธีที่ดีที่สุดในการตรวจสอบการมีอยู่ของคอลัมน์
Xenos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.