Sprawdź, czy tabela istnieje bez użycia opcji „wybierz z”


176

Czy istnieje sposób sprawdzenia, czy tabela istnieje bez wybierania i sprawdzania z niej wartości?

To znaczy, wiem, że mogę SELECT testcol FROM testtablesprawdzić liczbę zwróconych pól, ale wydaje się, że musi istnieć bardziej bezpośredni / elegancki sposób, aby to zrobić.


Odwiedź stackoverflow.com/a/167680/12495091, aby uzyskać odpowiedź !!!!!!!!!
Saurabh Chopra

@SaurabhChopra To dla SQL Server, to pytanie o MySql.
Alejandro

Odpowiedzi:


323

Jeśli chcesz być poprawny, użyj INFORMATION_SCHEMA .

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

Alternatywnie możesz użyć SHOW TABLES

SHOW TABLES LIKE 'yourtable';

Jeśli w zestawie wyników znajduje się wiersz, tabela istnieje.


3
Tak, to działa ładnie i jest eleganckie, ale nadal używa SELECT...FROMskładni ... Szukałem czegoś takiegoEXISTS testtable
Ben

9
Sposób, w jaki Marc i ja postanowiliśmy to zrobić, jest właściwy. Nie ma instrukcji typu „istnieje” MySql. „Exists” w MySql to klauzula, która wymaga operacji, takiej jak SELECT, UPDATE lub DELETE.
doogle

@Steve Trzecia opcja nie jest przenośna.
ta.speot.is

1
@SergioTulentsev Niezależnie od tagu wolę sposób przenośny od zastrzeżony.
ta.speot.is

1
@Filype to naprawdę nie jest problem, ponieważ sprawdza tylko, czy zapytanie się powiodło, czy nie. W przypadku, gdy tabela nie ma wierszy, zapytanie nadal się powiedzie, tylko z pustym zestawem wyników.
Bill Dami

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

jeśli otrzymasz niezerową liczbę, tabela istnieje.


2
Naprawdę nie rozumiem, co się tutaj stało. Sprawdziłem odpowiedzi, bo robię to teraz i to prawda, że ​​odpowiedź Sergio Tulentseva była wcześniejsza (1 min) i zaproponował 3 rozwiązania, ale to jest najskuteczniejsze. Dlaczego powinienem wybierać coś więcej lub cokolwiek innego, czego chcę? W tym przypadku potrzebuję „boolean” 1/0. Czy stół istnieje, czy nie. Nie chcę ograniczać wszystkiego, nie chcę niczego lubić, nie chcę żadnych błędów. To powinna być akceptowana odpowiedź.
vaso123

1
Zauważ, że na TEMPORARY TABLEto nie działa.
Thomas Lobker,

27

Porównanie wydajności:

  • MySQL 5.0.77 na bazie danych zawierającej około 11 000 tabel.
  • Wybieranie niedawno używanej tabeli, aby nie była przechowywana w pamięci podręcznej.
  • Uśredniona z 10 prób każda. (Uwaga: zrobiono z różnymi tabelami, aby uniknąć buforowania).

322 ms: show tables like 'table201608';

691 ms: select 1 from table201608 limit 1;

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

Zwróć uwagę, że jeśli korzystasz z tego dużo - na przykład w przypadku wielu żądań HTML w krótkim okresie - drugi będzie znacznie szybszy, ponieważ będzie przechowywany w pamięci podręcznej średnio 200 ms lub szybciej.


16

Możesz wysłać zapytanie do tableswidoku systemowego INFORMATION_SCHEMA :

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

Jeśli nie zwrócono żadnych wierszy, tabela nie istnieje.


9

Po przeczytaniu powyższego wolę następujące stwierdzenie:

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

Wskazuje dokładnie, co chcesz zrobić, i w rzeczywistości zwraca wartość „boolean”.


2
powinna to być zaakceptowana odpowiedź. zwięzłe i proste
Dika

to nie zwraca wartości boolowskiej, zwraca zestaw wyników. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
camslice


7

Oto tabela, która nie jest SELECT * FROM

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

Mam to od profesjonalisty bazy danych, oto co mi powiedziano:

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

Najłatwiejsze i wydajniejsze.
e2-e4

3

Powyższe zmodyfikowane rozwiązanie nie wymaga znajomości aktualnej bazy danych. Jest wtedy bardziej elastyczny.

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

2

Aby dodać dodatkowy sposób, aby to zrobić, iw zależności od tego, czego potrzebujesz, możesz użyć modułu obsługi dla błędu er_no_such_table : 1146 w ten sposób:

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

pokaż tabele, takie jak „nazwa_tabeli”

jeśli zwraca wiersze> 0, tabela istnieje


1

Możesz zrobić coś takiego jak poniżej:

            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

Rozszerzając tę odpowiedź , można by dalej napisać funkcję, która zwraca PRAWDA / FAŁSZ na podstawie tego, czy tabela istnieje, czy nie:

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

Ta kompaktowa metoda zwraca 1, jeśli istnieje 0, jeśli nie istnieje.

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

Możesz wstawić do funkcji 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 ;

i nazwij to

Select ExistTable('my_table');

zwraca 1 jeśli istnieje 0 jeśli nie istnieje.


0

Używam tego w 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

Z odpowiedziami należy zwrócić uwagę na kilka kwestii:

1) INFORMATION_SCHEMA.TABLESczy nie zawierają tabele tymczasowe.

2) Korzystanie z dowolnego typu SHOWzapytania, tjSHOW TABLES LIKE 'test_table' Wymusi zwrócenie zestawu wyników do klienta, co jest niepożądanym zachowaniem przy sprawdzaniu, czy tabela istnieje po stronie serwera, z procedury składowanej, która również zwraca zestaw wyników.

3) Jak wspomnieli niektórzy użytkownicy, musisz uważać podczas używania SELECT 1 FROM test_table LIMIT 1 .

Jeśli zrobisz coś takiego:

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

Nie uzyskasz oczekiwanego wyniku, jeśli tabela ma zero wierszy.

Poniżej znajduje się procedura składowana, która będzie działać dla wszystkich tabel (nawet TYMCZASOWYCH).

Może być używany jako:

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;

Kod:

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

To była moja procedura ISTNIEJE, która sprawdza zarówno tabele temp, jak i normalne. Ta procedura działa w MySQL w wersji 5.6 i nowszych. Parametr @DEBUG jest opcjonalny. Zakładany jest domyślny schemat, ale można go połączyć z tabelą w instrukcji @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 ;

Oto przykładowa instrukcja call z włączonym @debug:

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

Zmienna @tblExists zwraca wartość logiczną.


-1

Żadna z opcji oprócz SELECT nie zezwala na nazwę bazy danych używaną w SELECT, więc napisałem to:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.