Проверьте, существует ли таблица, не используя «select from» - PullRequest
138 голосов
/ 12 января 2012

Есть ли способ проверить, существует ли таблица без выбора и проверки значений из нее?

То есть я знаю, что могу пойти SELECT testcol FROM testtable и проверить количество полейвернулся, но, похоже, должен быть более прямой / элегантный способ сделать это.

Ответы [ 15 ]

1 голос
/ 19 апреля 2015

Просто чтобы добавить дополнительный способ сделать это, и в зависимости от того, что вам нужно, вы можете использовать обработчик для er_no_such_table ошибка: 1146 как это:

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 ;
0 голосов
/ 08 марта 2019

Есть несколько вопросов, на которые следует обратить внимание при ответах:

1) INFORMATION_SCHEMA.TABLES не не включает таблицы TEMPORARY.

2) Использование любого типа *Запрос 1008 *, то есть 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);

Вы не получите ожидаемый результат, еслитаблица содержит ноль строк.

Ниже приведена хранимая процедура, которая будет работать для всех таблиц (даже ВРЕМЕННЫХ).

Может использоваться следующим образом:

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 ;
0 голосов
/ 19 октября 2018

Расширяя этот ответ , можно дополнительно написать функцию, которая возвращает 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');
0 голосов
/ 02 августа 2016

Я использую это в 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 голосов
/ 06 января 2013

Ни один из параметров, кроме SELECT, не позволяет использовать имя базы данных, используемое в SELECT, поэтому я написал следующее:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...