Ruby
CentOS
SQLServer

CentOS7上のRubyスクリプトからMS SQLserverを操作する等

はじめに

SQLserverのバックアップ/リストア、レプリケーション処理のパフォーマンスの測定をする必要が生じたので、Rubyの強力なイテレーション機能を使用して任意のデータ作成を行うための自分メモです。

環境はVMware上のCentOS7,Ruby2.5.1から、母艦のWin機(win10)にインストールしたSQL Server 2017(14.0)への接続を行っています。

パッケージのインストール

まずはCentOSへSQLServerに接続する為のライブラリ「freetds」をインストールします。

# sudo yum install freetds freetds-devel

続いてRubyからfreetdsを使用する為のgem「tiny_tds」をインストールします。

# sudo yum install freetds freetds-devel

接続テスト

SQLserverへのDCNを記載したスクリプトで接続可否を確かめます。
参考:https://dev.classmethod.jp/server-side/server/connect_with_sqlserver_by_tiny_tds/

接続ホスト名はお使いの環境に合わせてください。
(今回のケースでは母艦側のipconfig/allの結果とVM側からのping結果等から割り出してIPを直書きしてますが、/etc/hosts等で名前解決しても行けると思います。)

# frozen_string_literal: true
# get_time.sql
require 'tiny_tds'
begin
  client = TinyTds::Client.new username: 'sa', password: 'password', host: '192.168.132.1'
  sql = client.escape('select @@version as str')
  result = client.execute(sql)
  result.each do |row|
    p row
  end
ensure
  client.close if client&.active?
end

上記スクリプトを実行するとハッシュ形式でレスポンスの取得が出来ました。

# ruby sql.rb
{"str"=>"Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64) \n\tAug 22 2017 17:04:49 \n\tCopyright (C) 2017 Microsoft Corporation\n\tDeveloper Edition (64-bit) on Windows 10 Pro 10.0 <X64> (Build 16299: )\n"}

テストデータ作成スクリプト1:INSERT文での実行

とりあえず、SQLserverに接続が出来たので、INSERT文でのデータ挿入を試みました。
※処理がスタックする場合、コメントアウトされたsleep処理を有効にすると上手く動作しましたが、詳細な原因分析は出来ておりません。。

require 'tiny_tds'
begin
  puts 'start:' + Time.now.to_s # 開始時刻出力
  # SQLserver connection
  client = TinyTds::Client.new username: 'sa', password: 'password', host: '192.168.132.1'
  insert_rec = 100000;   # ぶち込むレコード件数を定義
  1.upto(insert_rec) do |i|
    tmp ="INSERT INTO [database_name].[dbo].[table_name] (column1,column2,column3) values ('f_name_#{i}','#{'a'*fs}'0);"
    EOF
    print '*' if (i % 10)==0 # 進捗確認用
    # DML exec
    result = client.execute(tmp)
    # print sql_execute status
    result.each do |row|
      p row
    end
    tmp = ''
    # sleep(1) if (i % 3)==0  #状況により、コメントアウト解除でインターバルを設ける。
  end
  puts ''
ensure
  # close connection
  client.close if client&.active?
  puts 'end:' + Time.now.to_s  # 終了時刻出力
end