テーブルDDLから列名を抽出する

テーブルDDLから列名を抽出する

テーブルのリストを含むテキストファイルがあります。各テーブルの列を抽出し、テーブル名とともに別のcsvファイルに作成する必要があります。

はい

describe test_table
+-----------+------------+
| col_name  | data_type  |
+-----------+------------+
| Name      | string     |
| Age       | string     |
+-----------+------------+

次の詳細でcsvファイルを作成する必要があります。

test_table,Name,Age

何か提案してもらえますか?

答え1

すべてのUnixシステムのすべてのシェルでawkを使用してください。

$ cat tst.awk
$1 == "describe" {
    out = $2
    next
}
/^[+]/ {
    mod = (++cnt % 3)
    if ( mod == 0 ) {
        print out
    }
    next
}
mod == 2 {
    out = out "," $2
}

$ awk -f tst.awk file
test_table,Name,Age

答え2

Perlでこれを行う1つの方法の例は次のとおりです。

$ cat extract-column-names.pl
#!/usr/bin/perl -l

while(<>) {
  # Is the current line a "describe" line or are we at the End Of File?
  if (m/describe\s+(.*)/i || eof) {
    # Do we already a table name and column names?
    if ($table && @columns) {
      print join(",", $table, @columns);
      # clear current @columns array
      @columns=();
    };
    # extract table name
    $table = $1;
    next;
  };

  # skip header lines, ruler lines, and empty lines
  next if (m/col_name|-\+-|^\s*$/);

  # extract column name with regex capture group
  if (m/^\|\s+(\S+)\s+\|/) { push @columns, $1 };
}

複数のテーブル記述を含む入力の例:

$ cat table.txt
describe test_table
+-----------+------------+
| col_name  | data_type  |
+-----------+------------+
| Name      | string     |
| Age       | string     |
+-----------+------------+

describe test_table2
+------------+------------+
| col_name   | data_type  |
+------------+------------+
| FirstName  | string     |
| MiddleName | string     |
| LastName   | string     |
+------------+------------+

実行例:

$ ./extract-column-names.pl table.txt
test_table,Name,Age
test_table2,FirstName,MiddleName,LastName

ただし、このスクリプトは標準入力(例cat table.txt | ./extract-column-names.pl:)と複数のファイル名引数(例./extract-column-names.pl table1.txt table2.txt ... tableN.txt:)も処理できます。

data_typeまた、各列を抽出する機能を追加することも難しくありません。これは、別の配列(たとえば)に保存されるか、ハッシュ(キーと値として使用される)を@types使用するようにスクリプトを変更できます。しかし、ハッシュを使用する場合、ハッシュは本質的に順序がないことを覚えておくことが重要です。したがって、列が表示される順序を覚えるには配列が必要です。col_namedata_type@columns


シングルラインバージョン:

$ perl -lne 'if (m/describe\s+(.*)/i || eof) {if ($table && @columns) {print join(",", $table, @columns);@columns=()}$table = $1;next};next if (m/col_name|-\+-|^\s*$/);if (m/^\|\s+(\S+)\s+\|/) {push @columns, $1};' table.txt 
test_table,Name,Age
test_table2,FirstName,MiddleName,LastName

答え3

テスト環境を準備します。

# Get all the table
mysql -S /var/run/mysqld/mysqld.sock -D mysql -e 'SHOW TABLES;' > all_tables

# Get all the column for each tables
xargs -a all_tables -i -- /bin/sh -c '
    printf "describe %s\\n" "$1"
    mysql -S /var/run/mysqld/mysqld.sock -D mysql -te "DESC $1"
' _Z_ {} >> tables

以下は抜粋です。ファイルはサンプルデータと同じです。

describe column_stats
+---------------+-----------------------------------------+------+-----+---------+-------+
| Field         | Type                                    | Null | Key | Default | Extra |
+---------------+-----------------------------------------+------+-----+---------+-------+
| db_name       | varchar(64)                             | NO   | PRI | NULL    |       |
| table_name    | varchar(64)                             | NO   | PRI | NULL    |       |
| column_name   | varchar(64)                             | NO   | PRI | NULL    |       |
| min_value     | varbinary(255)                          | YES  |     | NULL    |       |
| max_value     | varbinary(255)                          | YES  |     | NULL    |       |
| nulls_ratio   | decimal(12,4)                           | YES  |     | NULL    |       |
| avg_length    | decimal(12,4)                           | YES  |     | NULL    |       |
| avg_frequency | decimal(12,4)                           | YES  |     | NULL    |       |
| hist_size     | tinyint(3) unsigned                     | YES  |     | NULL    |       |
| hist_type     | enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') | YES  |     | NULL    |       |
| histogram     | varbinary(255)                          | YES  |     | NULL    |       |
+---------------+-----------------------------------------+------+-----+---------+-------+
describe columns_priv
+-------------+----------------------------------------------+------+-----+---------------------+-------------------------------+
| Field       | Type                                         | Null | Key | Default             | Extra                         |
+-------------+----------------------------------------------+------+-----+---------------------+-------------------------------+
| Host        | char(60)                                     | NO   | PRI |                     |                               |
| Db          | char(64)                                     | NO   | PRI |                     |                               |
| User        | char(80)                                     | NO   | PRI |                     |                               |
| Table_name  | char(64)                                     | NO   | PRI |                     |                               |
| Column_name | char(64)                                     | NO   | PRI |                     |                               |
| Timestamp   | timestamp                                    | NO   |     | current_timestamp() | on update current_timestamp() |
| Column_priv | set('Select','Insert','Update','References') | NO   |     |                     |                               |
+-------------+----------------------------------------------+------+-----+---------------------+-------------------------------+

以下を使用して解析しますawk

awk -F'|' -v OFS=, '
    match($0, /^describe /) {
        tbl = substr($0, RSTART+RLENGTH)
        c = 3
        next
    } 

    /^[+]/ && c < 0 {print tbl}

    c-- <= 0 {
        gsub(/ */, "", $2)
        tbl = tbl OFS $2
    } 
' tables

関連情報