Быстрый поиск определенного столбца для определенных ключевых слов с помощью хранимой процедуры
Я написал хранимую процедуру, которая получает:
- "SearchKeys" - ключи для поиска, разделенные "," "key1, key2"
- "ToSearch" - таблицы для поиска в разделенных "," с колонками после ":" разделенных "." "Table1:column1.column2,table2:column1.column2"
В конце процедуры возвращается таблица с именем таблицы и идентификатором строки, в которой был найден ключ.
вот код:
--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 ответ
Самое первое, о чем я здесь предупрежу, это то, что ваша процедура широко открыта для инъекционной атаки. Инъекционная атака сама по себе является широкой темой. Если вам интересно, я предлагаю прочитать эту статью. Если вам абсолютно необходим интерфейс этого типа (то есть вы не можете использовать статический тип 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 + '%'