SQLServerでのMidB関数
レガシーマイグレーションで帳票の印字内容で全角・半角文字を意識した処理があり、バイト数指定の文字列関数が必要になりました。
http://blogs.sqlpassj.org/yoshihirokawabata/archive/2006/08/03/17581.aspxにLeftB, RightBはあったので、MidB関数の第3引数省略版を作りました。
LeftB, RightBの類推で作るとこんな感じ。
CREATE FUNCTION MidB ( @value varchar(8000), @start int, @length int ) RETURNS varchar(8000) AS BEGIN RETURN convert(varchar(8000), substring(convert(text, @value), @start, @length)) END GO
第3引数を省略したバージョンはこちら。
CREATE FUNCTION AfterB ( @value varchar(8000), @start int ) RETURNS varchar(8000) AS BEGIN RETURN convert(varchar(8000), substring(convert(text, @value), @start, datalength(convert(text, @value)) - @start + 1)) END GO
しかし、切り出す境界で2バイト文字をまたいでしまうとまずいです。。。うーん。。。
LeftB関数の戻り値は2バイト文字をまたいで切り出しても、切り捨ててくれるようですのでAfterB関数はこれを利用します。
/* AfterB: 第3引数を省略したバイト単位の Mid (substring) ユーザー定義関数 ■実行例 dbo.AfterB('あいうえお', 5) = 'うえお' 参考:http://blogs.sqlpassj.org/yoshihirokawabata/archive/2006/08/03/17581.aspx */ CREATE FUNCTION AfterB ( @all varchar(8000), @start int ) RETURNS varchar(8000) AS BEGIN DECLARE @left varchar(8000) SET @left = dbo.LeftB(@all, @start - 1) RETURN substring(@all, len(@left) + 1, len(@all) - len(@left)1) END GO
下記のクエリを実行して確認します。意図どおりのようです。
SELECT DATALENGTH(dbo.LeftB('あいうえお', 3)),DATALENGTH(dbo.AfterB('あいうえお', 4))
MidB関数はAfterB関数の戻り値を利用して、こうしてみます。
/* MidB: バイト単位の Mid (substring) ユーザー定義関数 ■実行例 dbo.MidB('あいうえお', 5, 2) = 'う' 参考:http://blogs.sqlpassj.org/yoshihirokawabata/archive/2006/08/03/17581.aspx */ CREATE FUNCTION MidB ( @value0 varchar(8000), @start int, @length int ) RETURNS varchar(8000) AS BEGIN DECLARE @value varchar(8000) SET @value = dbo.AfterB(@value0, @start - 1) RETURN dbo.LeftB(@value, @length) END GO
MidB関数の仕様が妥当かは検討の余地がありますが、2バイト文字をぶった切るために起こる文字化けを防げますし、とりあえずこうしておきます。
#今回のお仕事で必要なのはAfterB関数だけだし。:-P
PASSJの河端様にはいつも助けられてます。m(_ _)m