我需要创建一个搜索我正在构建的Java应用程序,用户可以根据他们当前正在查看的表以及他们提供的搜索词来搜索SQL数据库。起初我会做这样简单的事情:
SELECT * FROM <table name> WHERE CAST((SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table name>')
AS VARCHAR) LIKE '%<search term>%'
但该子查询返回多个结果,因此我尝试创建一个过程来遍历给定表中的所有列,并将任何相关字段放在结果表中,如下所示:
CREATE PROC sp_search
@tblname VARCHAR(4000),
@term VARCHAR(4000)
AS
SET nocount on
SELECT COLUMN_NAME
INTO #tempcolumns
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tblname
ALTER TABLE #tempcolumns
ADD printed BIT,
num SMALLINT IDENTITY
UPDATE #tempcolumns
SET printed = 0
DECLARE @colname VARCHAR(4000),
@num SMALLINT
WHILE EXISTS(SELECT MIN(num) FROM #tempcolumns WHERE printed = 0)
BEGIN
SELECT @num = MIN(num)
FROM #tempcolumns
WHERE printed = 0
SELECT @colname = COLUMN_NAME
FROM #tempcolumns
WHERE num = @num
SELECT * INTO #results FROM @tblname WHERE CAST(@colname AS VARCHAR)
LIKE '%' + @term + '%' --this is where I'm having trouble
UPDATE #tempcolumns
SET printed = 1
WHERE @num = num
END
SELECT * FROM #results
GO
这有两个问题:首先是它以某种方式陷入无限循环,其次我无法从@tblname中选择任何东西。我也试过使用动态sql,但我不知道如何从中得到结果,或者甚至可能。
这是我在大学时所做的一项任务,经过几个小时的努力来解决这个问题后,我已经做到了这一点。有什么办法可以做我想做的事吗?
答案 0 :(得分:0)
你进入一个无限循环,因为即使没有匹配,EXISTS(SELECT MIN(num) FROM #tempcolumns WHERE printed = 0)
总会返回一行 - 你需要EXISTS (SELECT * ....
而不是
要使用动态SQL,您需要构建要运行的SQL语句的字符串(varchar),然后使用EXEC
例如:
declare @s varchar(max)
select @s = 'SELECT * FROM mytable '
Exec (@s)
答案 1 :(得分:0)
PROCEDURE
而非PROC
- 它不是“prock”,而是“存储过程”。 dbo.
(or alternate schema) prefix when referencing any object。BEGIN
/ END
。@tblname
而不是@tablename
或@table_name
?我不是为了一个特定的会议而奋斗,但是以可读性为代价来节省字符在70年代失去了它的魅力。sp_
前缀 - 此前缀在SQL Server中具有特殊含义。为该程序命名程序。它不需要前缀,就像我们知道即使没有tbl
前缀它们也是表。如果您确实需要一个前缀,请使用usp_
或proc_
之类的前缀,但我个人认为该前缀不会为您提供任何您尚未拥有的信息。NVARCHAR
,而不是VARCHAR
。标识符的上限为128个字符,因此没有理由支持&gt; @tablename
的257个字符。INFORMATION_SCHEMA
- 虽然后者是你的教授所教导和可能期望的。 CREATE PROCEDURE dbo.SearchTable
@tablename NVARCHAR(257),
@term NVARCHAR(4000)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'SELECT * FROM ' + @tablename + ' WHERE 1 = 0';
SELECT @sql = @sql + '
OR ' + c.name + ' LIKE ''%' + REPLACE(@term, '''', '''''') + '%'''
FROM
sys.all_columns AS c
INNER JOIN
sys.types AS t
ON c.system_type_id = t.system_type_id
AND c.user_type_id = t.user_type_id
WHERE
c.[object_id] = OBJECT_ID(@tablename)
AND t.name IN (N'sysname', N'char', N'nchar',
N'varchar', N'nvarchar', N'text', N'ntext');
PRINT @sql;
-- EXEC sp_executesql @sql;
END
GO
如果您对正在输出的SELECT
查询感到满意,请注释掉PRINT
并取消注释EXEC
。