none
求解CLR应用正则运算match 的sql语法 RRS feed

  • 问题

  • 小弟目前碰到个CASE 是需要匹配数据表正则运算 regex

     

    在这里也查看了CSDN上有讨论 ms sql上有用regex的范例

     

    http://blog.csdn.net/jinjazz/article/details/4101746

     

    但我还是遇上了麻烦

     

    我的CLR 程序:

     

    Imports System
    
    Imports System.Data
    
    Imports System.Data.SqlClient
    
    Imports System.Data.SqlTypes
    
    Imports Microsoft.SqlServer.Server
    
    Imports System.Text.RegularExpressions
    
     
    
     
    
     
    
    Partial Public Class StoredProcedures
    
     
    
        <SqlFunction()> _
    
      Public Shared Function regexes(ByVal expression As SqlString) As SqlString
    
     
    
            Dim regex As Regex = New Regex(" ")         ' Split on hyphens.
    
            'Dim substrings() As String = regex.Split("plum * pear * BALL")
    
            Dim substrings() As String = regex.Split(expression)
    
            Dim c As String = vbNullString
    
            For Each match As String In substrings
    
                If match = "*" Then '匹配有通配符才转换
    
                    match = ".*"
    
                End If
    
                c += match & " "
    
            Next
    
            Dim c1 As String = c.Trim(" ") 'Trim截去前后不必要的
    
            Dim regex1 As String = c1
    
     
    
            Return regex1 '返回值相当于 regexes = pattern
    
     
    
        End Function
    
     
    
        <SqlFunction()> _
    
        Public Shared Function regexismatch(ByVal input As SqlString, ByVal pattern As SqlString) As SqlBoolean
    
     
    
            If input.IsNull OrElse pattern.IsNull Then
    
                Return False
    
            End If
    
            Return Regex.IsMatch(input.Value, pattern.Value)
    
     
    
        End Function
    
     
    
        <SqlFunction()> _
    
        Public Shared Function regexmatch(ByVal input As SqlString, ByVal pattern As SqlString) As SqlString
    
     
    
            If input.IsNull OrElse pattern.IsNull Then
    
     
    
            End If
    
            Dim inputx As String = input
    
            Dim patternx As String = pattern
    
     
    
            Dim m As Match = Regex.Match(inputx, patternx)
    
            If m.Success Then
    
                Return input
    
            Else
    
                Return False
    
            End If
    
        End Function
    
    End Class




    我写了三个函式  目前只用到两个 regexes, regexmatch

     

    目前我的case是这样

     


     

    要将这张数据表下的patter栏的字符串转成 regex 输入做匹配

     

    输入正确就会回传输入字符串 这里用regexmatch  然后找出相对应的 template

     

    目前小弟只知道将patter栏的字符串转成 regex这项工作

     

    但和转成 regex的集和做匹配的sql 语法 小弟不知道该怎么写

     

    这是我目前写的sql 和 碰到的错误信息

    select * from aiml2
    select dbo.regexes(pattern) from aiml2 -- 轉成regex的語法 
    declare @t table(regex varchar(max))
    declare @regex varchar(max)=@t
    declare @input varchar(max)= 'ok ones'
    select dbo.regexes(pattern) from aiml2  where  dbo.regexmatch(@input,@regex)>0

     

    讯息 137,层级 16,状态 1,行 2

    必须宣告纯量变量 "@t"

     

    还请各位大大指点一下迷津


    • 已编辑 向恩 2012年6月9日 15:45
    2012年6月9日 15:41

答案

  • --我本地没有vs环境,我用两个函数先代替一下,就是个思路问题。
    /*
    create function dbo.regexes (@p varchar(4))
    returns varchar(10)
    as
    begin
    return @p+'a'
    end
    go
    
    create function dbo.regexmatch(@a varchar(10),@b varchar(10))
    returns varchar(10)
    as
    begin
    return @a+@b
    end
    */
    --上面两个函数就是两个函数,没有实际意义,就是为了我本地能够正常运行。
    
    --假设这是你的aiml2的数据
    declare @aiml2 table (pattern varchar(2))
    insert into @aiml2
    select 'a1' union all
    select 'b1' union all
    select 'c1' union all
    select 'd1'
    
    --你现在的实现方式
    declare @regex varchar(max)
    select @regex = dbo.regexes(pattern) from @aiml2
    select @regex
    
    declare @input varchar(max) set @input='ok ONES'
    select dbo.regexmatch(@input,@regex)
    
    --你现在的结果,只处理了一行
    /*
    ok ONESd1a
    */
    
    --应该是这样的,不用@t也是可以的。
    declare @input1 varchar(max) set @input1='ok ONES'
    select dbo.regexmatch(@input1,dbo.regexes(pattern)) from @aiml2
    /*
    ok ONESa1a
    ok ONESb1a
    ok ONESc1a
    ok ONESd1a
    */

    • 已标记为答案 向恩 2012年6月10日 5:41
    2012年6月10日 4:24
    版主

全部回复

  • 你把@t表变量赋值给varchar变量了,是会报错的。

    --貌似你是要两个表做匹配:
    select * from aiml2 
    select dbo.regexes(pattern) from aiml2 -- 轉成regex的語法 
    declare @t table(regex varchar(max))
    declare @input varchar(max)= 'ok ones'
    select dbo.regexes(pattern) from aiml2 a,@t b  
    where  dbo.regexmatch(@input,b.regex)>0

    不对呀?你的@t是空的呀?没有插入内容呀?






    2012年6月10日 3:25
    版主
  • 我現在是不曉得 這邊的程式碼該怎麼寫 我這裡的SQL程式碼是不完整的

    我目前的思路是

    declare @t table(regex varchar(max))

    insert into @t select dbo.regexes(pattern) from aiml2 -- 轉成regex的集合資料

    把資料轉成regex 集合資料後 存到@t 這個暫存表 然後再將這個暫存表的regex 抽出來跟輸入資料 @input做匹配

    declare @input varchar(max)= 'ok ones'
    dbo.regexmatch(@input,<集合regex的資料> )

    但問題是出在 這行不能接受table 型別的變量

    <集合regex的資料>

    2012年6月10日 3:42
  • 我刚刚把它改成

    declare @regex varchar(max)

    select @regex = dbo.regexes(pattern) from aiml2

    select @regex

    declare @input varchar(max)='ok ONES'

    select dbo.regexmatch(@input,@regex)

    虽然这样可以做匹配了  但是这样的写法 只会输出regex集合中的最后一行来跟input 做匹配

    @regex

    所以这样还是不行  請問大家這邊有什麼好的思路可以用呢?


    2012年6月10日 3:59
  • --插入@t后,这样不可以吗?
    select dbo.regexmatch(@input,a.regex ) from @t a



    2012年6月10日 4:13
    版主
  • --我本地没有vs环境,我用两个函数先代替一下,就是个思路问题。
    /*
    create function dbo.regexes (@p varchar(4))
    returns varchar(10)
    as
    begin
    return @p+'a'
    end
    go
    
    create function dbo.regexmatch(@a varchar(10),@b varchar(10))
    returns varchar(10)
    as
    begin
    return @a+@b
    end
    */
    --上面两个函数就是两个函数,没有实际意义,就是为了我本地能够正常运行。
    
    --假设这是你的aiml2的数据
    declare @aiml2 table (pattern varchar(2))
    insert into @aiml2
    select 'a1' union all
    select 'b1' union all
    select 'c1' union all
    select 'd1'
    
    --你现在的实现方式
    declare @regex varchar(max)
    select @regex = dbo.regexes(pattern) from @aiml2
    select @regex
    
    declare @input varchar(max) set @input='ok ONES'
    select dbo.regexmatch(@input,@regex)
    
    --你现在的结果,只处理了一行
    /*
    ok ONESd1a
    */
    
    --应该是这样的,不用@t也是可以的。
    declare @input1 varchar(max) set @input1='ok ONES'
    select dbo.regexmatch(@input1,dbo.regexes(pattern)) from @aiml2
    /*
    ok ONESa1a
    ok ONESb1a
    ok ONESc1a
    ok ONESd1a
    */

    • 已标记为答案 向恩 2012年6月10日 5:41
    2012年6月10日 4:24
    版主
  • 恩 這種寫法測試了一下可以了  不過之前都沒看過這種寫法 一時間還真想不出可以這樣寫

    declare @input1 varchar(max) set @input1='ok ONES'
    select dbo.regexmatch(@input1,dbo.regexes(pattern)) from aiml2

    在觀念上 這算是函式中的箝套嗎?

    2012年6月10日 5:41
  • 查询还有嵌套子查询呢,何况是个函数...

    2012年6月10日 6:04
    版主
  • 長知識了  謝謝!
    2012年6月10日 7:30