マルチバイト文字を含む文字列の部分取得#SQL

以下ファンクションの説明をして
CREATE FUNCTION dbo.MIDB (@str nvarchar(max), @start int, @length int)
RETURNS nvarchar(max)
AS
BEGIN
    DECLARE @result nvarchar(max)
    SET @result = SUBSTRING(@str, @start, @length / (CASE WHEN @str LIKE N'%[^ -~。-゚]%' THEN 2 ELSE 1 END))
    RETURN @result
END

===============

この関数 dbo.MIDB は、指定された文字列 (@str) から指定された開始位置 (@start) と長さ (@length) に基づいて部分文字列を返すものです。ただし、この関数はマルチバイト文字(全角文字)を考慮しています。

具体的には、以下のように動作します:

@result という変数を宣言します。この変数に最終的な結果が格納されます。
SUBSTRING 関数を使用して、指定された文字列 (@str) から部分文字列を抽出します。開始位置は @start で、長さは @length です。
ただし、長さ (@length) は特殊な計算によって決定されます。具体的には、@str がマルチバイト文字(全角文字)を含む場合、長さは @length / 2 となります。これは、マルチバイト文字が2バイトを占めるためです。一方、@str がシングルバイト文字(半角文字)のみを含む場合、長さは @length のままです。
最後に、抽出した部分文字列 @result を返します。
したがって、この関数はマルチバイト文字とシングルバイト文字を適切に処理するための MID 関数のバージョンと考えることができます。全角と半角の文字を混在させた文字列を扱う際に便利です。

===============

-- 関数の作成
CREATE FUNCTION dbo.MIDB (@str nvarchar(max), @start int, @length int)
RETURNS nvarchar(max)
AS
BEGIN
    DECLARE @result nvarchar(max)
    SET @result = SUBSTRING(@str, @start, @length / (CASE WHEN @str LIKE N'%[^ -~。-゚]%' THEN 2 ELSE 1 END))
    RETURN @result
END
GO

-- 関数の使用
DECLARE @myString nvarchar(max) = N'こんにちは、世界!'
SELECT dbo.MIDB(@myString, 1, 4) AS 'Result'
===============

上記のコードでは、dbo.MIDB 関数を使用して、@myString という変数から部分文字列を抽出しています。開始位置は 1 で、長さは 4 です。結果は Result という名前の列に表示されます。

ただし、この関数はマルチバイト文字(全角文字)を考慮しているため、4 と指定した場合でも、実際には2文字(全角文字2文字分)が抽出されます。この例では、こんにちは、世界! の最初の2文字、つまり こ と ん が抽出されます。

なお、SQL Serverの環境がない場合は、オンラインのSQLエディタを使用しても同様の結果を得ることができます。ただし、オンラインのSQLエディタでは、一部の関数や機能が制限されている場合がありますのでご注意ください。また、セキュリティ上の理由から、機密情報を含むクエリはオンラインのSQLエディタで実行しないでください。

===============

N'%[^ -~。-゚]%' は 何を意味していますか

===============

N'%[^ -~。-゚]%' は、SQLのLIKE句で使用されるパターンです。このパターンは、マルチバイト文字(全角文字)を検出するために使用されます。

具体的には、以下のような意味を持っています:

  • ^:否定を表します。つまり、[^ -~。-゚]-~。-゚ のいずれの文字も含まないことを意味します。
  • -~:ASCII文字の範囲を表します。つまり、半角文字(スペースからチルダまでのすべての半角文字)を表します。
  • 。-゚:全角文字の範囲を表します。つまり、全角の句読点から全角のチルダまでのすべての全角文字を表します。

したがって、[^ -~。-゚] は半角文字と全角文字のいずれも含まない、つまりマルチバイト文字を含むことを意味します。

そして、% は任意の文字列を表します。したがって、N'%[^ -~。-゚]%' は、任意の位置にマルチバイト文字を含む文字列に一致します。

このパターンは、LIKE 句と一緒に使用され、文字列がマルチバイト文字を含むかどうかを判断します。例えば、@str LIKE N'%[^ -~。-゚]%' は、@str がマルチバイト文字を含む場合に TRUE を返します。それ以外の場合は FALSE を返します。この結果は、関数 dbo.MIDB 内で部分文字列の長さを決定するために使用されます。全角文字が含まれている場合、長さは @length / 2 となります。それ以外の場合、長さは @length のままです。これにより、全角文字と半角文字を適切に処理することができます。

 

mysqlテスト検証サンプル

以下は、Mysqlのプロシージャ呼び出しにて負荷テストを実行するPowerShellスクリプトです。
条件を満たすように記述されており、可変となる設定はPowerShellコマンドライン引数として指定可能です。

```powershell
# SQLファイルのパスを指定
$sqlFilePath = "C:\path\to\sqlfile.sql"

# Mysql接続情報を指定
$connectionString = "Database=mydb;Data Source=localhost;User Id=myuser;Password=mypassword"

# スレッド数、多重度、SQL実行回数、Sleep時間をPowerShellコマンドライン引数から取得
$numThreads = [int]$args[0]
$concurrency = [int]$args[1]
$numIterations = [int]$args[2]
$sleepTimeSeconds = [int]$args[3]

# 前処理でスレッド数を出力
Write-Host "Starting load test with $numThreads threads and $concurrency concurrency." -ForegroundColor Cyan

# カウンタを初期化
$threadsStarted = 0

# スレッド(トランザクション)のメイン処理を定義
function ExecuteTransactions {
    # グローバル変数の$threadsStartedと$numThreadsを使用するためにScopeをグローバルに変更
    $global:threadsStarted += 1
    Write-Host "Thread $global:threadsStarted started." -ForegroundColor Green

    # Mysqlコネクションを確立
    $conn = New-Object System.Data

.SqlClient.SqlConnection
    $conn.ConnectionString = $connectionString
    $conn.Open()

    # 多重度分だけトランザクションを実行
    for ($i = 0; $i -lt $concurrency; $i++) {
        # SQLファイルからSQL文を取得
        $sql = Get-Content $sqlFilePath

        # 取得したSQL文を実行
        for ($j = 0; $j -lt $numIterations; $j++) {
            $cmd = New-Object System.Data.SqlClient.SqlCommand($sql, $conn)
            $cmd.ExecuteNonQuery()
        }

        # 指定されたスリープ時間待機
        Start-Sleep -Seconds $sleepTimeSeconds
    }

    # 処理完了時にMysqlコネクションを切断
    $conn.Close()

    # グローバル変数の$threadsStartedと$numThreadsを使用するためにScopeをグローバルに変更
    $global:threadsStarted -= 1
    Write-Host "Thread finished. $global:threadsStarted threads remaining." -ForegroundColor Red
}

# スレッドを生成し開始する
for ($i = 0; $i -lt $numThreads; $i++) {
    Start-Job -ScriptBlock { ExecuteTransactions }
}

# 実行中のスレッド数を定期的に監視し、0になったら終了する
while ($threadsStarted -gt 0) {
    Write-Host "Waiting for $global:threadsStarted threads to finish..." -ForegroundColor Yellow
    Start-Sleep -Seconds 10
}

# 後処理で負荷テストが完了しましたら、どのような結果が得られたか確認することが重要です。負荷テストの結果を分析することで、負荷に耐えられる限界、性能の制限点、ボトルネック、障害の原因などが分かります。これにより、改善点を特定してより良いパフォーマンスのシステムを設計することができます。