SQL Serverで文字列をByte数で切り取ろうとすると結構大変だった。
経緯
他システムから固定長のファイルが送られてくるので、それを利用側(SQL Server 2019)で使いやすいように列を分割しようとしたらハマった。
※bcp ユーティリティを使えばもっと楽にできたのかもしれないが、今回は分け合ってSQLで対応しなければならなかった。
結論
断っておくが今回は固定長の為、切り取ろうとしている位置に全角文字(2Byte文字)が来ることはあり得ない。
試していないが全角文字と途中で切ると、1Byte少ない文字列が返ってくるらしい。
record_valueカラムの7Byte目から4Byte切り取る場合
元データ | やりたいこと |
---|---|
あいうえおかきくけこ | えお |
REVERSE(CONVERT(VARCHAR(4), REVERSE(CONVERT(VARCHAR(10), [record_value]))))
解説
Step1
VARCHARにCONVERTする事でLEFT関数のByte版になる。
record_value | CONVERT(VARCHAR(10), [record_value]) |
---|---|
あいうえおかきくけこ | あいうえお |
ここでは必要となる文字列を含んだByte数で区切る。
これで第1段階はクリア。あとは前から余分な文字をそぎ落とす。
Step2
REVERSE関数を使えば文字列を反転させる事ができる。
record_value | REVERSE(CONVERT(VARCHAR(10), [record_value])) |
---|---|
あいうえおかきくけこ | おえういあ |
Step3
Step1とStep2の応用。
取り出したいByte数でVARCHARに変換し、REVERSEで元の文字列を再度反転させる。
record_value | REVERSE(CONVERT(VARCHAR(4), REVERSE(CONVERT(VARCHAR(10), [record_value])))) |
---|---|
あいうえおかきくけこ | えお |
補足
なぜこんな回り道をしなければならないかと言うと、
- SUBSTRING関数が文字数を指定。
- LEN関数が末尾の空白を除いた文字数を返してしまう。( 固定長ファイルの操作で致命的 )
といった事があるため。
固定長嫌い。