Cách bỏ bảng trống


11

Có thể bỏ tất cả các bảng trống từ cơ sở dữ liệu khổng lồ của tôi (mysql) không?

Tôi đang tìm kiếm một lệnh sql để tự động loại bỏ tất cả các bảng trống.

Hiện tại, tôi có 305 bảng trong tập dữ liệu của mình và khoảng 30% trong số đó là các bảng trống cũ, sẽ không được sử dụng trong ứng dụng mới của tôi.

Chỉ cần làm rõ; Tất cả các bảng có loại = MyISAM


1
Là tất cả các bảng MyISAM, InnoDB hoặc hỗn hợp của cả hai ???
RolandoMySQLDBA

Tất cả đều là MyISAM
vòng loại

Câu trả lời:


11

Ý tưởng có lẽ là tìm kiếm các bảng trống bằng cách sử dụng INFORMATION_SCHEMA.TABLES

SELECT * 
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_ROWS =  '0'
AND TABLE_SCHEMA = 'my_database_only'

Sau đó, bạn có thể tạo một truy vấn SQL với

SELECT CONCAT('DROP TABLE ', GROUP_CONCAT(table_name), ';') AS query
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_ROWS = '0'
AND TABLE_SCHEMA = 'my_database_only';

Nhanh và hơi bẩn, nhưng thực sự nên làm việc.


3
... và sau đó bạn có một máy chủ cơ sở dữ liệu bị hỏng vì bạn "có thể" đã xóa một số bảng hệ thống mysql ... bên cạnh thực tế là CONCAT của bạn tạo ra một danh sách bảng mà không cần tham chiếu lược đồ.
Cristian Porta

1
Bạn cũng có "quyền" để thêm thông minh các hạn chế cơ sở dữ liệu vào các bảng của mình, tôi nghĩ đó là điều hiển nhiên.
Tom Desp

3
câu trả lời không nên được chấp nhận vì câu trả lời có khả năng gây nguy hiểm cho người dùng ... chỉ vậy thôi
Cristian Porta

2
+1 để thiết lập một lệnh DROP TABLE.
RolandoMySQLDBA

1
@CP: Ok tôi hiểu rồi, lỗi lầm khủng khiếp của tôi, đó là lý do tại sao tôi chỉnh sửa câu trả lời. Nhân tiện, tôi hơi ngạc nhiên khi một truy vấn SQL thực sự có thể làm rơi bảng nội bộ của hệ thống MySQL. Từ quan điểm của tôi, đó là hoàn toàn bị phá vỡ.
Tom Desp

7

Vì tất cả các bảng là MyISAM, điều này làm cho câu trả lời của tôi dễ diễn đạt hơn.

Trước tiên, bạn cần truy vấn Information_SCHema cho các bảng có hàng không:

SELECT table_schema,table_name FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema');

Tiếp theo, xây dựng truy vấn để thả các bảng trống:

SELECT CONCAT('DROP TABLE ',table_schema,'.',table_name,';') DropTableCommand
FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema');

Bây giờ, kết xuất các lệnh vào một tệp văn bản SQL bên ngoài.

SQL="SELECT CONCAT('DROP TABLE ',table_schema,'.',table_name,';') DropTableCommand"
SQL="${SQL} FROM information_schema.tables WHERE table_rows = 0 AND table_schema"
SQL="${SQL} NOT IN ('information_schema','mysql','performance_schema')"
mysql -uroot -p -ANe"${SQL}" > DropTables.sql

Nhìn vào nội dung với một trong những điều sau đây

  • less DropTables.sql
  • cat DropTables.sql

Nếu bạn hài lòng với nội dung của nó, hãy chạy tập lệnh:

mysql -uroot -p < DropTables.sql

hoặc đăng nhập vào mysql và chạy nó như thế này:

mysql> source DropTables.sql

Hãy thử một lần !!!

CAVEAT : Kỹ thuật này chỉ hoạt động với bảng MyISAM vì số hàng của bảng MyISAM được lưu trữ vật lý trong .MYDcác bảng. Bảng siêu dữ liệu Information_SCHema.TABLES luôn đọc và cập nhật. ĐỪNG THỬ NÀY VỚI INNODB !!!

CẬP NHẬT 2014 / 02-05 11:46 EST

Có một lý do tôi loại trừ ('information_schema','mysql','performance_schema')

Các mysqlsơ đồ có bàn còn trống trong đó. Một số MyISAM, một số InnoDB, một số CSV.

Ví dụ, đây là các bảng của tôi trong lược đồ mysql cho MySQL 5.6.15 trên máy tính để bàn của tôi

mysql> select table_name,engine,table_rows
    -> from information_schema.tables
    -> where table_schema='mysql';
+---------------------------+--------+------------+
| table_name                | engine | table_rows |
+---------------------------+--------+------------+
| columns_priv              | MyISAM |          0 |
| db                        | MyISAM |          2 |
| event                     | MyISAM |          0 |
| func                      | MyISAM |          0 |
| general_log               | CSV    |          2 |
| help_category             | MyISAM |         40 |
| help_keyword              | MyISAM |        485 |
| help_relation             | MyISAM |       1090 |
| help_topic                | MyISAM |        534 |
| innodb_index_stats        | InnoDB |          0 |
| innodb_table_stats        | InnoDB |          0 |
| ndb_binlog_index          | MyISAM |          0 |
| plugin                    | MyISAM |          0 |
| proc                      | MyISAM |          0 |
| procs_priv                | MyISAM |          0 |
| proxies_priv              | MyISAM |          1 |
| servers                   | MyISAM |          0 |
| slave_master_info         | InnoDB |          0 |
| slave_relay_log_info      | InnoDB |          0 |
| slave_worker_info         | InnoDB |          0 |
| slow_log                  | CSV    |          2 |
| tables_priv               | MyISAM |          0 |
| time_zone                 | MyISAM |          0 |
| time_zone_leap_second     | MyISAM |          0 |
| time_zone_name            | MyISAM |          0 |
| time_zone_transition      | MyISAM |          0 |
| time_zone_transition_type | MyISAM |          0 |
| user                      | MyISAM |          6 |
+---------------------------+--------+------------+
28 rows in set (0.01 sec)

mysql>

Nếu một số những bảng đã biến mất (như columns_priv, proc_priv, tables_priv, vv), cơ chế tài trợ có thể không hoạt động đúng hoặc có thể gây ra mysqld không khởi động. Bạn cũng không muốn đánh cắp mysql.proc vì đây là ngôi nhà thực sự của các thủ tục được lưu trữ. Các cơ chế khác có thể không hoạt động nếu bạn muốn sử dụng chúng, chẳng hạn như Sao chép CrashSafe bằng cách sử dụng các bảng InnoDB bên trong lược đồ mysql hoặc nếu bạn muốn chèn thông tin múi giờ.

CẬP NHẬT 2014 / 02-05 12:36 EST

Tôi muốn khen ngợi Tom Desp vì câu trả lời của anh ấy vì một lý do cụ thể: Cú pháp của anh ấy có thể thực hiện việc thả mà không cần sử dụng tập lệnh bên ngoài . Sử dụng ý tưởng của anh ấy, hãy để tôi bắt lệnh DROP TABLE thành một biến do người dùng định nghĩa.

SELECT CONCAT('DROP TABLE ',GROUP_CONCAT(DBTB),';')
INTO @DropCommand
FROM (SELECT CONCAT(table_schema,'.',table_name) DBTB
FROM information_schema.tables
WHERE table_rows = 0 AND table_schema NOT IN
('information_schema','mysql','performance_schema')) A;
SELECT @DropCommand;

Nếu đầu ra của SELECT @DropCommand;chính xác, sau đó thực hiện lệnh như thế này:

PREPARE s FROM @DropCommand;
EXECUTE s;
DEALLOCATE PREPARE s;

Điều này giúp loại bỏ hai điều:

  • sự cần thiết của một tệp văn bản SQL bên ngoài
  • chạy một lệnh DROP TABLE riêng cho mỗi bảng

1
Cảm ơn cho một lời giải thích dài và tốt! +1 để trả về các bảng trên cơ sở dữ liệu. Cách này rất dễ dàng để làm sạch một số dữ liệu. Mặt khác; sử dụng cẩn thận. Tôi chạy truy vấn của bạn dựa vào "..AND table_schema = 'my_database_name'" để chỉ hoạt động với một cơ sở dữ liệu (như Tom Desp đã đề xuất trong một câu trả lời khác)
vòng
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.