Periksa apakah tabel ada tanpa menggunakan "pilih dari"


176

Apakah ada cara untuk memeriksa apakah ada tabel tanpa memilih dan memeriksa nilai dari itu?

Artinya, saya tahu saya bisa pergi SELECT testcol FROM testtabledan memeriksa jumlah bidang yang dikembalikan, tetapi tampaknya harus ada cara yang lebih langsung / elegan untuk melakukannya.


Kunjungi stackoverflow.com/a/167680/12495091 untuk jawabannya !!!!!!!!!
Saurabh Chopra

@ SaurabhChopra Itu untuk SQL Server, ini bertanya tentang MySql.
Alejandro

Jawaban:


323

Jika Anda ingin benar, gunakan INFORMATION_SCHEMA .

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

Atau, Anda dapat menggunakan SHOW TABLES

SHOW TABLES LIKE 'yourtable';

Jika ada baris di resultset, tabel ada.


3
Ya, itu bekerja dengan baik dan elegan, tetapi masih menggunakan SELECT...FROMsintaksis ... Saya sedang mencari sesuatu sepertiEXISTS testtable
Ben

9
Cara Marc dan saya menyatakan untuk melakukannya adalah cara yang tepat. Tidak ada pernyataan tipe 'ada' MySql. 'Ada' di MySql adalah klausa yang membutuhkan operasi seperti SELECT, UPDATE, atau DELETE.
doogle

@Steve Opsi ketiga tidak portabel.
ta.speot.is

1
@SergioTulentsev Terlepas dari tag, saya lebih suka cara portabel daripada cara yang eksklusif.
ta.speot.is

1
@Filype ini bukan masalah, karena dia hanya memeriksa apakah kueri berhasil atau tidak. Dalam kasus di mana tabel tidak memiliki baris, kueri akan tetap berhasil, hanya dengan set hasil kosong.
Bill Dami

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

jika Anda mendapatkan jumlah yang tidak nol, tabel ada.


2
Saya benar-benar tidak mengerti apa yang terjadi di sini. Saya sudah memeriksa jawabannya, karena saya melakukannya sekarang, dan memang benar jawaban Sergio Tulentsevs lebih awal (1 menit) dan menawarkan 3 solusi, tetapi yang ini paling efektif. Mengapa saya harus memilih sesuatu yang lebih atau apa pun yang saya inginkan? Saya membutuhkan "boolean" 1/0 dalam kasus ini. Apakah tabel ada atau tidak. Saya tidak ingin membatasi segalanya, saya tidak ingin menyukai apa pun, saya tidak ingin ada kesalahan. Ini harus menjadi jawaban yang diterima.
vaso123

1
Perhatikan bahwa TEMPORARY TABLEini tidak berfungsi.
Thomas Lobker

27

Perbandingan kinerja:

  • MySQL 5.0.77, pada db yang memiliki sekitar 11.000 tabel.
  • Memilih tabel yang belum lama digunakan sehingga tidak di-cache.
  • Rata-rata lebih dari 10 mencoba masing-masing. (Catatan: dilakukan dengan tabel yang berbeda untuk menghindari caching).

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

Catatan jika Anda sering menjalankan ini - seperti banyak permintaan HTML dalam waktu singkat - tanggal 2 akan jauh lebih cepat karena akan di-cache rata-rata 200 ms atau lebih cepat.


16

Anda dapat menanyakan tablestampilan sistem INFORMATION_SCHEMA :

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

Jika tidak ada baris yang dikembalikan, maka tabel tidak ada.


9

Setelah membaca semua hal di atas, saya lebih suka pernyataan berikut:

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

Ini menunjukkan apa yang ingin Anda lakukan dan sebenarnya mengembalikan 'boolean'.


2
ini seharusnya jawaban yang diterima. ringkas dan sederhana
Dika

ini tidak mengembalikan Boolean, ini mengembalikan set hasil. var_dump:mysqli_result Object ( [current_field] => 0 [field_count] => 1 [lengths] => [num_rows] => 1 [type] => 0 )
camslice


7

Ini adalah tabel yang bukan SELECT * FROM

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

Mendapat ini dari database pro, di sini adalah apa yang saya diberitahu:

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

Termudah dan efisien.
e2-e4

3

Solusi yang dimodifikasi dari atas ini tidak memerlukan pengetahuan eksplisit tentang database saat ini. Maka lebih fleksibel.

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

2

Hanya untuk menambahkan cara tambahan untuk melakukannya, dan tergantung pada apa yang Anda perlukan, Anda dapat menggunakan penangan untuk kesalahan er_no_such_table : 1146 seperti ini:

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

tampilkan tabel seperti 'table_name'

jika ini mengembalikan baris> 0 tabel ada


1

Anda dapat melakukan sesuatu seperti di bawah ini:

            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

Memperluas jawaban ini , seseorang dapat lebih lanjut menulis fungsi yang mengembalikan BENAR / SALAH berdasarkan apakah ada tabel:

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

Metode ringkas ini mengembalikan 1 jika ada 0 jika tidak ada.

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

Anda dapat dimasukkan ke dalam fungsi 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 ;

dan menyebutnya

Select ExistTable('my_table');

kembalikan 1 jika ada 0 jika tidak ada.


0

Saya menggunakan ini di 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

Ada beberapa masalah yang perlu diperhatikan dengan jawaban di sini:

1) INFORMATION_SCHEMA.TABLEStidak tidak termasuk tabel SEMENTARA.

2) Menggunakan segala jenis SHOWpermintaan, yaituSHOW TABLES LIKE 'test_table' , akan memaksa pengembalian set hasil ke klien, yang merupakan perilaku yang tidak diinginkan untuk memeriksa apakah tabel ada di sisi server, dari dalam prosedur tersimpan yang juga mengembalikan set hasil.

3) Seperti yang disebutkan beberapa pengguna, Anda harus berhati-hati dengan cara Anda menggunakannya SELECT 1 FROM test_table LIMIT 1.

Jika Anda melakukan sesuatu seperti:

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

Anda tidak akan mendapatkan hasil yang diharapkan jika tabel memiliki nol baris.

Di bawah ini adalah prosedur tersimpan yang akan bekerja untuk semua tabel (bahkan SEMENTARA).

Dapat digunakan seperti:

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;

Kode:

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

Ini telah menjadi prosedur 'pergi ke' untuk saya yang memeriksa temp dan tabel normal. Prosedur ini berfungsi di MySQL versi 5.6 ke atas. Parameter @DEBUG adalah opsional. Skema default diasumsikan, tetapi dapat digabungkan ke tabel dalam pernyataan @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 ;

Berikut ini contoh pernyataan panggilan dengan @debug pada:

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

Variabel @tblExists mengembalikan boolean.


-1

Tak satu pun dari opsi kecuali SELECT tidak mengizinkan nama database seperti yang digunakan dalam SELECT, jadi saya menulis ini:

SELECT COUNT(*) AS cnt FROM information_schema.TABLES 
WHERE CONCAT(table_schema,".",table_name)="db_name.table_name";
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.