J'ai un Master DB. Je veux créer une base de données en double de la base de données principale, mais pas toutes les tables spécifiées.
J'ai ces noms de table dans une chaîne séparée par des virgules. tbl1, tbl2, tbl7, tbl10
etc.
J'essaie de faire passer une procédure stockée new DB name
Cela crée la base de données et réplique la table donnée. Jusqu'à présent, j'ai 2 choses, mais je ne sais pas comment les parcourir. Je suis nouveau sur DB, veuillez guider comment y parvenir.
(Remarque) Je n'ai pas trouvé si un tableau peut être utilisé pour boucler, les noms de table peuvent également être stockés dans une variable de tableau, car les noms de table sont codé en dur.
Ce qui suit est le code Sudo que je désire.
CREATE DATABASE %param_db%;
@tables = 'tbl1, tbl2, tbl7, tbl10';
loop through @tables as table_name
CREATE TABLE %param_db.table_name% LIKE Master.%table_name%;
End loop
Voici les étapes de mise en page dans la procédure stockée
Voici cette procédure stockée
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`TableCookieCutter` $$
CREATE PROCEDURE `test`.`TableCookieCutter`
(
SourceDB VARCHAR(64),
TargetDB VARCHAR(64),
TableList VARCHAR(1024)
)
BEGIN
# Create the Target DB
SET @sql = CONCAT('CREATE DATABASE IF NOT EXISTS ',TargetDB);
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
# Strip Table List of Blanks
# Enclose each table in quotes
SET @table_list = CONCAT('''',REPLACE(REPLACE(TableList ,' ',''),',',QUOTE(',')),'''');
# Count the number of tables in the list
SET @table_stub = REPLACE(@table_list,',','');
SET @array_count = LENGTH(@table_list) - LENGTH(@table_stub) + 1;
# Loop through list of tables, creating each table
SET @x = 0;
WHILE @x < @array_count DO
SET @x = @x + 1;
SET @sql = CONCAT('SELECT ELT(',@x,',',@table_list,') INTO @tb');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @sql = CONCAT('CREATE TABLE ',TargetDB,'.',@tb,' LIKE ',SourceDB,'.',@tb);
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
END WHILE;
END $$
DELIMITER ;
@RolandoMySQLDBA le poste d'abord, mais j'ai une autre façon.
En utilisant ceci pour séparer la chaîne de virgule séparée et ceci pour le nombre d'occurrences , j'ai fait cette procédure stockée:
CREATE DEFINER=`root`@`localhost` PROCEDURE `spCreateRplDB`(
IN iNewDB VARCHAR(100),
IN iOldDB VARCHAR(100),
IN iTables VARCHAR(150))
BEGIN
# Comma separated string
SET @repldb=iNewDB;
SET @masterdb=iOldDB;
SET @tbls=TRIM(iTables);
SET @counter=(SELECT ROUND((LENGTH(@tbls) - LENGTH( REPLACE (@tbls, ",", ""))) / LENGTH(",")));
SET @loop_num=0;
# Splitting comma separated string
IF (@counter>0 && @repldb<>'' && @masterdb <> '') THEN
SET @counter=@counter+1; # [ ADDING +1 BECAUSE @counter JUST COUNT THE NUMBER OF OCCURENCES OF A STRING INSIDE @tbls ]
# Creating DB if not exists
SET @database_create=CONCAT(" CREATE DATABASE IF NOT EXISTS ",@repldb,";");
PREPARE database_create FROM @database_create;
EXECUTE database_create;
DEALLOCATE PREPARE database_create;
WHILE @loop_num<>@counter DO
SET @loop_num=@loop_num+1;
SET @rownumber=0; # Row Number
SET @tbl='';
SELECT
v.value
INTO @tbl
FROM (SELECT
TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(t.value, ',', n.n), ',', -1)) AS value,
@rownumber:=@rownumber+1 AS rownumber
FROM (SELECT @tbls AS value) AS t
CROSS JOIN (SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
) n
WHERE n.n <= 1 + (LENGTH(t.value) - LENGTH(REPLACE(t.value, ',', '')))
HAVING rownumber=@loop_num) AS v;
# Creating Table
SET @drop_table=CONCAT(" DROP TABLE IF EXISTS ",@repldb,".",@tbl,";");
SET @create_table=CONCAT(" CREATE TABLE ",@repldb,".",@tbl," LIKE ",@masterdb,".",@tbl,";");
# Preparing STMT for @drop_table
PREPARE droptable FROM @drop_table;
EXECUTE droptable;
DEALLOCATE PREPARE droptable;
# Preparing STMT for @create_table
PREPARE create_table FROM @create_table;
EXECUTE create_table;
DEALLOCATE PREPARE create_table;
END WHILE;
END IF;
END
@counter
, nombre d'occurrences de ,
( délimiteur de tables ).iNewDB
et iOldDB
n'est pas nul ou vide, continuez.iTables
.mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
| test_old |
+--------------------+
5 rows in set (0.00 sec)
mysql> SHOW TABLES IN test_old;
+--------------------+
| Tables_in_test_old |
+--------------------+
| test1 |
| test2 |
| test3 |
| test4 |
+--------------------+
4 rows in set (0.00 sec)
mysql>
mysql> CALL test.spCreateRplDB(
-> 'test_dev', # New DB
-> 'test_old', # Master DB
-> 'test1,test2,test4');
Query OK, 0 rows affected (0.01 sec)
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
| test_dev |
| test_old |
+--------------------+
6 rows in set (0.00 sec)
mysql> SHOW TABLES IN test_dev;
+--------------------+
| Tables_in_test_dev |
+--------------------+
| test1 |
| test2 |
| test4 |
+--------------------+
3 rows in set (0.00 sec)
mysql>