Kiểm tra xem bảng có tồn tại mà không sử dụng chọn hay không


176

Có cách nào để kiểm tra nếu một bảng tồn tại mà không chọn và kiểm tra các giá trị từ nó không?

Đó là, tôi biết tôi có thể đi SELECT testcol FROM testtablevà kiểm tra số lượng các trường được trả lại, nhưng có vẻ như phải có một cách trực tiếp / thanh lịch hơn để làm điều đó.


Truy cập stackoverflow.com/a/167680/12495091 để biết câu trả lời !!!!!!!!!
Saurabh Chopra

@SaurabhChopra Đó là cho SQL Server, đây là câu hỏi về MySql.
Alejandro

Câu trả lời:


323

Nếu bạn muốn chính xác, hãy sử dụng Information_SCHema .

SELECT * 
FROM information_schema.tables
WHERE table_schema = 'yourdb' 
    AND table_name = 'testtable'
LIMIT 1;

Ngoài ra, bạn có thể sử dụng SHOW TABLES

SHOW TABLES LIKE 'yourtable';

Nếu có một hàng trong tập kết quả, bảng tồn tại.


3
Vâng, nó hoạt động độc đáo và thanh lịch, nhưng vẫn sử dụng SELECT...FROMcú pháp ... Tôi đã tìm kiếm một cái gì đó nhưEXISTS testtable
Ben

9
Cách Marc và bản thân tôi tuyên bố để làm điều đó là cách thích hợp. Không có câu lệnh kiểu 'tồn tại' MySql. 'Tồn tại' trong MySql là một mệnh đề yêu cầu một thao tác như CHỌN, CẬP NHẬT hoặc XÓA.
doogle

@Steve Tùy chọn thứ ba không khả dụng.
ta.speot.is

1
@SergioTulentsev Bất kể thẻ nào tôi thích cách di động hơn cách độc quyền.
ta.speot.is

1
@Filype đây không thực sự là một vấn đề, vì anh ta chỉ kiểm tra xem truy vấn có thành công hay không. Trong trường hợp bảng không có hàng, truy vấn vẫn sẽ thành công, chỉ với một tập kết quả trống.
Bill Dami

66
SELECT count(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA = 'your_db_name') AND (TABLE_NAME = 'name_of_table')

nếu bạn nhận được một số khác không, bảng tồn tại.


2
Tôi thực sự không hiểu điều gì đã xảy ra ở đây. Tôi đã kiểm tra các câu trả lời, bởi vì tôi đang thực hiện nó và đúng là câu trả lời của Sergio Tulentsev đã sớm hơn (1 phút) và đưa ra 3 giải pháp, nhưng đây là cách hiệu quả nhất. Tại sao tôi nên chọn bất cứ thứ gì nhiều hơn hoặc bất cứ thứ gì tôi muốn? Tôi cần một "boolean" 1/0 trong trường hợp này. Bảng có tồn tại hay không. Tôi không muốn giới hạn mọi thứ, tôi không muốn bất cứ điều gì, tôi không muốn có bất kỳ lỗi nào. Đây phải là câu trả lời được chấp nhận.
vaso123

1
Lưu ý rằng trên TEMPORARY TABLEnày không hoạt động.
Thomas lobker

27

Một so sánh hiệu suất:

  • MySQL 5.0.77, trên một db có khoảng 11.000 bảng.
  • Chọn một bảng không được sử dụng gần đây để nó không được lưu trong bộ nhớ cache.
  • Tính trung bình trên 10 lần thử. (Lưu ý: được thực hiện với các bảng khác nhau để tránh bộ đệm).

322ms: show tables like 'table201608';

691ms: select 1 from table201608 limit 1;

319ms: SELECT count(*) FROM information_schema.TABLES WHERE (TABLE_SCHEMA = 'mydb') AND (TABLE_NAME = 'table201608');

Lưu ý nếu bạn đang chạy rất nhiều - như nhiều yêu cầu HTML trong một khoảng thời gian ngắn - lần thứ 2 sẽ nhanh hơn vì nó sẽ được lưu trong bộ nhớ cache trung bình 200 ms hoặc nhanh hơn.


16

Bạn có thể truy vấn tableschế độ xem hệ thống Information_SCHema :

SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'databasename'
AND table_name = 'testtable';

Nếu không có hàng nào được trả về, thì bảng không tồn tại.


9

Sau khi đọc tất cả những điều trên, tôi thích tuyên bố sau:

SELECT EXISTS(
       SELECT * FROM information_schema.tables 
       WHERE table_schema = 'db' 
       AND table_name = 'table'
);

Nó chỉ ra chính xác những gì bạn muốn làm và nó thực sự trả về một 'boolean'.


2
đây nên là câu trả lời được chấp nhận súc tích và đơn giản
Dika

cái này không trả về Boolean, nó trả về tập kết quả. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
camslice

7

Thay vì dựa vào lỗi, bạn có thể truy vấn INFORMATION_SCHEMA.TABLESđể xem bảng có tồn tại không. Nếu có một bản ghi, nó tồn tại. Nếu không có hồ sơ, nó không tồn tại.


1
Ahh, bây giờ chúng ta đang tiến gần hơn! Tôi sẽ đi thử.
Ben

1
@Steve: vẫn là a SELECT FROM. :-)
Sergio Tulentsev

7

Đây là bảng không phải là CHỌN * TỪ

SHOW TABLES FROM `db` LIKE 'tablename'; //zero rows = not exist

Có được điều này từ một cơ sở dữ liệu chuyên nghiệp, đây là những gì tôi đã nói:

select 1 from `tablename`; //avoids a function call
select * from IMFORMATION_SCHEMA.tables where schema = 'db' and table = 'table' // slow. Field names not accurate
SHOW TABLES FROM `db` LIKE 'tablename'; //zero rows = not exist

Dễ nhất và hiệu quả.
e2-e4

3

Giải pháp sửa đổi từ trên không yêu cầu kiến ​​thức rõ ràng về cơ sở dữ liệu hiện tại. Sau đó nó linh hoạt hơn.

SELECT count(*) FROM information_schema.TABLES WHERE TABLE_NAME = 'yourtable' 
AND TABLE_SCHEMA in (SELECT DATABASE());

2

Chỉ cần thêm một cách để làm điều đó và tùy thuộc vào những gì bạn cần nó, bạn có thể sử dụng trình xử lý cho lỗi er_no_such_table : 1146 như thế này:

DELIMITER ;;
CREATE PROCEDURE `insert_in_my_table`(in my_var INT)
BEGIN
   -- Error number for table not found
   DECLARE CONTINUE HANDLER FOR 1146
   BEGIN
      -- table doesn't exists, do something...
      CREATE TABLE my_table(n INT);
      INSERT INTO my_table (n) values(my_var);
   END;
      -- table does exists, do something...
      INSERT INTO my_table (n) values(my_var);
END ;;
DELIMITER ;

2

hiển thị các bảng như 'tên_bảng'

nếu điều này trả về hàng> 0 thì bảng tồn tại


1

Bạn có thể làm một cái gì đó như dưới đây:

            string strCheck = "SHOW TABLES LIKE \'tableName\'";
            cmd = new MySqlCommand(strCheck, connection);
            if (connection.State == ConnectionState.Closed)
            {
                connection.Open();
            }
            cmd.Prepare();
            var reader = cmd.ExecuteReader();
            if (reader.HasRows)
            {                             
              Console.WriteLine("Table Exist!");
            }
            else
            {                             
              Console.WriteLine("Table does not Exist!");
            }

1

Mở rộng câu trả lời này , người ta có thể viết thêm một hàm trả về TRUE / FALSE dựa trên việc bảng có tồn tại hay không:

CREATE FUNCTION fn_table_exists(dbName VARCHAR(255), tableName VARCHAR(255))
  RETURNS BOOLEAN
  BEGIN
    DECLARE totalTablesCount INT DEFAULT (
      SELECT COUNT(*)
      FROM information_schema.TABLES
      WHERE (TABLE_SCHEMA COLLATE utf8_general_ci = dbName COLLATE utf8_general_ci)
        AND (TABLE_NAME COLLATE utf8_general_ci = tableName COLLATE utf8_general_ci)
    );
    RETURN IF(
      totalTablesCount > 0,
      TRUE,
      FALSE
    );
END
;


SELECT fn_table_exists('development', 'user');

1

Phương thức rút gọn này trả về 1 nếu tồn tại 0 nếu không tồn tại.

set @ret = 0; 
SELECT 1 INTO @ret FROM information_schema.TABLES 
         WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'my_table'; 
SELECT @ret;

Bạn có thể đưa vào một chức năng mysql

DELIMITER $$
CREATE FUNCTION ExistTable (_tableName varchar(255))
RETURNS tinyint(4)
SQL SECURITY INVOKER
BEGIN
  DECLARE _ret tinyint;
  SET _ret = 0;
  SELECT
    1 INTO _ret
  FROM information_schema.TABLES
  WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME = _tablename LIMIT 1;
  RETURN _ret;
END
$$
DELIMITER ;

và gọi nó

Select ExistTable('my_table');

trả về 1 nếu tồn tại 0 nếu không tồn tại.


0

Tôi sử dụng điều này trong php.

private static function ifTableExists(string $database, string $table): bool
    {
        $query = DB::select("
            SELECT 
                IF( EXISTS 
                    (SELECT * FROM information_schema.COLUMNS
                        WHERE TABLE_SCHEMA = '$database'
                        AND TABLE_NAME = '$table'
                        LIMIT 1),
                1, 0)
                AS if_exists
        ");

        return $query[0]->if_exists == 1;
    }

0

Có một số vấn đề cần lưu ý với câu trả lời ở đây:

1) INFORMATION_SCHEMA.TABLESkhông không bao gồm các bảng TẠM.

2) Sử dụng bất kỳ loại SHOWtruy vấn nào, nghĩa là SHOW TABLES LIKE 'test_table', sẽ trả lại kết quả cho máy khách, đây là hành vi không mong muốn để kiểm tra xem bảng có tồn tại phía máy chủ hay không, từ bên trong một thủ tục được lưu trữ cũng trả về kết quả.

3) Như một số người dùng đã đề cập, bạn phải cẩn thận với cách bạn sử dụng SELECT 1 FROM test_table LIMIT 1 .

Nếu bạn làm một cái gì đó như:

SET @table_exists = 0;
SET @table_exists = (SELECT 1 FROM test_table LIMIT 1);

Bạn sẽ không nhận được kết quả như mong đợi nếu bảng không có hàng.

Dưới đây là một quy trình được lưu trữ sẽ hoạt động cho tất cả các bảng (thậm chí TẠM THỜI).

Nó có thể được sử dụng như:

SET @test_table = 'test_table';
SET @test_db = NULL;
SET @does_table_exist = NULL;

CALL DoesTableExist(@test_table, @test_db, @does_table_exist);

SELECT @does_table_exist;

Mật mã:

/*
    p_table_name is required
    p_database_name is optional
        if NULL is given for p_database_name, then it defaults to the currently selected database
    p_does_table_exist
        The @variable to save the result to

    This procedure attempts to
        SELECT NULL FROM `p_database_name`.`p_table_name` LIMIT 0;

    If [SQLSTATE '42S02'] is raised, then
        SET p_does_table_exist = 0
    Else
        SET p_does_table_exist = 1

    Info on SQLSTATE '42S02' at:
        https://dev.mysql.com/doc/refman/5.7/en/server-error-reference.html#error_er_no_such_table
*/

DELIMITER $$

DROP PROCEDURE IF EXISTS DoesTableExist
$$

CREATE PROCEDURE         DoesTableExist (
    IN p_table_name VARCHAR(64),
    IN p_database_name VARCHAR(64),
    OUT p_does_table_exist TINYINT(1) UNSIGNED
)
BEGIN
    /* 793441 is used in this procedure for ensuring that user variables have unique names */

    DECLARE EXIT HANDLER FOR SQLSTATE '42S02'
    BEGIN
        SET p_does_table_exist = 0
        ;
    END
    ;


    IF p_table_name IS NULL THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'DoesTableExist received NULL for p_table_name.';
    END IF;


    /* redirect resultset to a dummy variable */

    SET @test_select_sql_793441 = CONCAT(
        "SET @dummy_var_793441 = ("
            " SELECT"
                " NULL"
            " FROM ",
                IF(
                    p_database_name IS NULL,
                    "",
                    CONCAT(
                        "`",
                        REPLACE(p_database_name, "`", "``"),
                        "`."
                    )
                ),
                "`",
                REPLACE(p_table_name, "`", "``"),
                "`"
            " LIMIT 0"
        ")"
    )
    ;

    PREPARE _sql_statement FROM @test_select_sql_793441
    ;
    SET @test_select_sql_793441 = NULL
    ;
    EXECUTE _sql_statement
    ;
    DEALLOCATE PREPARE _sql_statement
    ;

    SET p_does_table_exist = 1
    ;
END
$$

DELIMITER ;

0

Đây là quy trình EXISTS 'go-to' của tôi để kiểm tra cả bảng tạm thời và bảng bình thường. Quy trình này hoạt động trong phiên bản MySQL 5.6 trở lên. Tham số @DEBUG là tùy chọn. Lược đồ mặc định được giả sử, nhưng có thể được nối với bảng trong câu lệnh @s.

drop procedure if exists `prcDoesTableExist`;
delimiter #
CREATE PROCEDURE `prcDoesTableExist`(IN pin_Table varchar(100), OUT pout_TableExists BOOL)
BEGIN
    DECLARE `boolTableExists` TINYINT(1) DEFAULT 1;
    DECLARE CONTINUE HANDLER FOR 1243, SQLSTATE VALUE '42S02' SET `boolTableExists` := 0;
        SET @s = concat('SELECT null FROM `', pin_Table, '` LIMIT 0 INTO @resultNm');
    PREPARE stmt1 FROM @s;
    EXECUTE stmt1;
    DEALLOCATE PREPARE stmt1;
    set pout_TableExists = `boolTableExists`; -- Set output variable
    IF @DEBUG then
        select IF(`boolTableExists`
            , CONCAT('TABLE `', pin_Table, '` exists: ', pout_TableExists)
            , CONCAT('TABLE `', pin_Table, '` does not exist: ', pout_TableExists)
        ) as result;
    END IF;
END #
delimiter ;

Dưới đây là câu lệnh gọi ví dụ với @debug trên:

set @DEBUG = true;
call prcDoesTableExist('tempTable', @tblExists);
select @tblExists as '@tblExists';

Biến @tblExists trả về một boolean.


-1

Không có tùy chọn nào ngoại trừ SELECT không cho phép tên cơ sở dữ liệu như được sử dụng trong SELECT, vì vậy tôi đã viết điều này:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.