有没有一种方法来检查表是否存在,而不选择和检查它的值?

也就是说,我知道我可以去SELECT testcol FROM testtable并检查返回字段的计数,但似乎必须有一个更直接/优雅的方式来做到这一点。


当前回答

扩展这个答案,可以进一步编写一个函数,根据表是否存在返回TRUE/FALSE:

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');

其他回答

我在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;
    }

如果想要正确,请使用INFORMATION_SCHEMA。

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

或者,您也可以使用SHOW TABLES

SHOW TABLES LIKE 'yourtable';

如果结果集中有行,则表存在。

这是我的“去”EXISTS过程,检查临时表和正常表。此过程适用于MySQL 5.6及以上版本。@DEBUG参数是可选的。默认模式是假设的,但是可以在@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 ;

下面是@debug on的示例调用语句:

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

变量@tblExists返回一个布尔值。

显示像'table_name'这样的表

如果返回行> 0,则表存在

这里的答案有几个问题需要注意:

1) INFORMATION_SCHEMA。TABLES不包括TEMPORARY表。

2)使用任何类型的SHOW查询,即SHOW TABLES LIKE 'test_table',将强制返回一个结果集到客户端,这是检查表是否存在服务器端的不希望的行为,从存储过程中也返回一个结果集。

3)正如一些用户提到的,你必须小心如何使用SELECT 1 FROM test_table LIMIT 1。

如果你这样做:

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

如果表中没有行,则不会得到预期的结果。

下面是一个适用于所有表(甚至是TEMPORARY表)的存储过程。

它可以这样使用:

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;

代码:

/*
    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 ;