1. 基本
  2. 複数行のクエリ

基本

シェルスクリプトでMySQLのコマンドやSQLを実行して結果を標準出力に出力する方法についての説明。 基本は以下のシェルでMySQLのコマンドやSQLを実行する方法になります。

テスト環境は、CentOS 6.6、MySQL 5.5.46 になります。

  • サンプル

  • あるデータベースの全テーブ名を取得して、各テーブルごとにdescribeコマンド実行するサンプル 各テーブルごとに、テーブル名とdescribeコマンドの結果を出力します。

    #!/bin/sh
    
    if [ "$1" = "" ]; then
        cat <<-EOS
        usage  $0 [db name]
    
    EOS
        exit
    fi
    
    DB=$1
    OPTIONS="-u root -D $DB"
    
    # 指定したデーベースのテーブル名を全て取得
    CMD="echo 'show tables;' | mysql $OPTIONS -N"
    TABLES=(`eval $CMD`)
    
    # 各テーブルごとにdescribeコマンドを実行
    for table in "${TABLES[@]}"
    do
        CMD="echo 'desc $table' | mysql $OPTIONS"
        echo "$table"
        eval "$CMD"
        echo
    done			
    ※上記の結果は1行目にテーブル名の"cond_instances"、2行目に出力項目名、3~4行目にテーブル"cond_instances"のカラム情報・・・と標準出力に出力されます。

    実行はデータベース名を指定します。データベース名が"performance_schema"の場合、以下のようになります。

    $ sh desc.sh performance_schema
    cond_instances
    Field   Type    Null    Key     Default Extra
    NAME    varchar(128)    NO              NULL
    OBJECT_INSTANCE_BEGIN   bigint(20)      NO              NULL
    
    ...  省略
    
    
    threads
    Field   Type    Null    Key     Default Extra
    THREAD_ID       int(11) NO              NULL
    PROCESSLIST_ID  int(11) YES             NULL
    NAME    varchar(128)    NO              NULL

    その他のサンプルは以下

複数行のクエリ

複雑なSQLは、複数行にしてインデントを使うと見やすくなります。 この場合、変数を使用するか、ヒアドキュメントを使います。

  • 変数を使って複数行のクエリを実行

  • 変数の代入では、シングルクォートやダブルクォートを使うと、その間で改行することができるので、 以下のようにSQLを複数行に分けることができます。

    #!/bin/sh
    
    DB=mysql$
    
    SQL="
    use $DB;
    SELECT
        Host, User,
       Select_priv,
       Insert_priv,
       Update_priv,
       Delete_priv,
       Grant_priv
       FROM user
    "
    echo "$SQL" | mysql -u root
    注意 変数にSQLを代入して使う場合、出力時にダブルクォートで囲みます。

     ただし、一部の文字(例 "*")に注意する必要があります。、  これはワイルドカード("*")などが変数展開されたりして意図していない文字列になる可能性があるからです。 そのため、SQLの入った変数を表示するときはダブルクォートで囲む必要があります。 上記例では、最後の行のechoのダブルクォートを削除すると、意図したSQLが実行されません。

    例 "*"が展開される場合
    #!/bin/sh
    
    DB=mysql
    
    SQL="
    use $DB
    SELECT * FROM user
    "
    
    echo $SQL
    echo $SQL | mysql -u root
    このスクリプト名が"heredoc_test.sh"で、同じディレクトリにファイル"readme.txt"がある場合 実行結果は以下のようになります。 これは"*"の箇所に実行ディレクトリのファイル名が展開されたためです。
    $ sh heredoc_test.sh
    use mysql SELECT heredoc_test.sh readme.txt FROM user
    そのため、変数にSQLを代入して使用する場合、出力では必ず変数をダブルクォートで囲む必要があります。

  • ヒアドキュメントを変数に代入して利用

  • 変数を使う場合、ヒアドキュメントを使うことも可能ですが、普通に変数への代入を使った方が簡単です。 ヒアドキュメントを変数に代入して使うのは以下のようにできます。

    #!/bin/sh
    
    DB=mysql
    
    SQL=`cat << EOS
    use $DB
    SELECT
      Host, User,
      Select_priv,
      Insert_priv,
      Update_priv,
      Delete_priv,
      Grant_priv
      FROM user
    EOS`
    
    echo "$SQL" | mysql -u root

    これを実行すると以下のような出力になります。

    $ sh here_document.sh
    Host    User    Select_priv     Insert_priv     Update_priv     Delete_priv     Grant_priv
    localhost       root    Y       Y       Y       Y       Y
    127.0.0.1       root    Y       Y       Y       Y       Y
    localhost               N       N       N       N       N
    localhost       mysqladmin      Y       Y       Y       Y       N
    localhost       redmine N       N       N       N       N

  • ヒアドキュメントでSQLを実行

  • 実行するSQL文自体を表示する必要が無い場合は、ヒアドキュメントを直接mysqlコマンドに投げます。

    #!/bin/sh
    
    DB=test_db
    
    mysql -u root << EOS
    use $DB
    SELECT
      Host, User,
      Select_priv,
      Insert_priv,
      Update_priv,
      Delete_priv,
      Grant_priv
      FROM user
    EOS