具有存储过程的特定关键字的快速搜索特定列

时间:2015-01-08 20:56:49

标签: sql sql-server search stored-procedures search-engine

我编写了一个存储过程:

  • " SearchKeys" - 用'分隔的搜索键,' " KEY1,KEY2"
  • " ToSearch" - 要搜索的表格,用','在'之后用colums:'由'分隔。' "表1:column1.column2,表2:column1.column2"

在最后一个过程返回表,其中包含表名和行ID,找到了密钥。

这是代码:

--Search keys in tables
CREATE PROCEDURE [dbo].[Search_All]
(
    @SearchKeys nvarchar(50), --Keys to search separated by ','
    @ToSearch varchar(200) --Tables to search in separated by ',' with colums after ':' separated by '.'
)
AS
BEGIN
    --create table with found values
    CREATE TABLE #Results (TargetId int, DBName varchar(20))

    --Split SearchKeys to Keys
    WHILE LEN(@SearchKeys) > 0
     BEGIN
        DECLARE @Key NVARCHAR(25)
        IF CHARINDEX(',',@SearchKeys) > 0
            SET  @Key = SUBSTRING(@SearchKeys,0,CHARINDEX(',',@SearchKeys))
        ELSE
            BEGIN
            SET  @Key = @SearchKeys
            SET @SearchKeys = ''
        END
        --Split ToSearch to Tables
        WHILE LEN(@ToSearch) > 0
         BEGIN
            DECLARE @TableAndColums VARCHAR(200)
            IF CHARINDEX(',',@ToSearch) > 0
                SET  @TableAndColums = SUBSTRING(@ToSearch,0,CHARINDEX(',',@ToSearch))
            ELSE
                BEGIN
                SET  @TableAndColums = @ToSearch
                SET @ToSearch = ''
                END
            SET @ToSearch = REPLACE(@ToSearch,@TableAndColums + ',' , '')
            --Split @TableAndColums to Table and Colums
            --Select Table
            DECLARE @Table VARCHAR(25)
            SET  @Table = SUBSTRING(@TableAndColums,0,CHARINDEX(':',@TableAndColums))
            SET @TableAndColums = REPLACE(@TableAndColums,@Table + ':' , '')
            --Split to Colums
            WHILE LEN(@TableAndColums) > 0
             BEGIN
                DECLARE @Column VARCHAR(25)
                IF CHARINDEX('.',@TableAndColums) > 0
                    SET  @Column = SUBSTRING(@TableAndColums,0,CHARINDEX('.',@TableAndColums))
                ELSE
                    BEGIN
                    SET  @Column = @TableAndColums
                    SET @TableAndColums = ''
                    END

                    BEGIN
                --insert result in to #Results table
                INSERT INTO #Results
                EXEC
                    (
                        'SELECT ' + @Table + '.Id AS ''TargetId'', '''+@Table+''' AS ''DBName''
                        FROM ' + @Table +
                        ' WHERE  ' + @Column + ' LIKE N''%' + @Key + '%'''
                    )
                END

             SET @TableAndColums = REPLACE(@TableAndColums,@Column + '.' , '')
            END
         END
     SET @SearchKeys = REPLACE(@SearchKeys,@Key + ',' , '')
    END
    --return found values
    SELECT DISTINCT TargetId , DBname FROM #Results
END

由于某种原因,它只搜索忽略所有其余键的第一个键。我不明白为什么会这样。请帮忙!

1 个答案:

答案 0 :(得分:1)

我在这里警告你的第一件事是你的程序对注射攻击是敞开的。注入攻击本身就是一个广泛的话题。如果您有兴趣,我建议您阅读这篇文章。如果你确实需要这种类型的接口(即你不能使用静态类型的SQL或类似于Entity Framework的东西来处理你的查询),你必须必须确保在运行时执行任何字符串(例如@column,@ table,@ key)是参数化或括号。如所写的,当输入的表不包含ID列或者当输入的列不存在时,该过程也将失败。

http://www.sommarskog.se/dynamic_sql.html

就你如何进行字符串拆分而言,我会看下面的文章。虽然没有办法消除循环每个表的需要,但是通过使用像本文中提到的字符串夹板函数将所有搜索字符串放入表中,您可以一次搜索单个表上的所有搜索条件。像这样:

select *
from #SearchConditions a
inner join dbo.TargetTable b
    on b.Name like '%' + a.SearchKey + '%'

http://www.sqlservercentral.com/articles/Tally+Table/72993/