web-dev-qa-db-ja.com

カンマ区切り値でループ

マスターDBがあります。マスターDBの複製DBを作成したいのですが、すべてのテーブルを指定しただけではありません。

カンマ区切りの文字列でこれらのテーブル名を持っています。 tbl1, tbl2, tbl7, tbl10など.

私はそれを渡すストアドプロシージャを作成しようとしていますnew DB nameこれにより、DBが作成され、指定されたテーブルがそれに複製されます。これまでのところ2つありますが、ループする方法がわかりません。私はDBが初めてなので、これを達成する方法を教えてください。

配列を使用してループできるかどうかはわかりませんが、テーブル名は配列変数に格納できます。テーブル名はハードコーディング

以下は私が望むSudoコードです。

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
5
Bsienn

ストアドプロシージャでレイアウトする手順は次のとおりです

  • ターゲットデータベースを作成する
  • テーブルのリストにある要素の数を特定する
  • ELT()関数 を使用して、テーブルのリストの各要素をループします。
  • 各要素を取得してSQLステートメントを作成し、ターゲットDBに新しいテーブルを作成します

これがそのストアドプロシージャです

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 ;
7
RolandoMySQLDBA

@RolandoMySQLDBAが最初に投稿しますが、別の方法があります。

これを 分割されたコンマ文字列区切り および これは発生数 に使用して、このストアドプロシージャを作成しました。

保存された手順:

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

プロセス:

  1. @counter,の出現回数(tables delimiter)。
  2. 出現回数が0を超え、iNewDBiOldDBがnullまたは空でない場合は、続行します。
  3. 新しいデータベースを作成します(iNewDB)。
  4. 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> 
2
oNare