我试图在SQL Server中编写一个存储过程,将列作为参数。用户将从组合框中选择列名称,并在文本框中写入该列的搜索值。
我一直在寻找如何做到这一点,到目前为止我有这个:
ALTER PROCEDURE [dbo].[SP_Select_TBL_Folio]
@cant int,
@Column1 nvarchar(50),
@Value1 nvarchar(50),
@Column2 nvarchar(50),
@Value2 nvarchar(50),
@Column3 nvarchar(50),
@Value3 nvarchar(50)
AS
BEGIN
declare @query nvarchar (max)
SET NOCOUNT ON;
if @cant = 1
BEGIN
set @query = 'SELECT * FROM TBL_Folio WHERE ' + @Column1 + ' LIKE '+ @Value1 + ' ORDER BY 1 DESC';
exec sp_executesql @query, N' '
END
else
BEGIN
if @cant = 2
BEGIN
set @query = 'SELECT * FROM TBL_Folio WHERE ' + @Column1 + ' LIKE '+ @Value1 + ' AND ' + @Column2 + ' LIKE '+ @Value2 + ' ORDER BY 1 DESC';
exec sp_executesql @query, N' '
END
ELSE
if @cant = 3
BEGIN
set @query = 'SELECT * FROM TBL_Folio WHERE ' + @Column1 + ' LIKE '+ @Value1 + ' AND ' + @Column2 + ' LIKE '+ @Value2 + ' AND ' + @Column3 + ' LIKE '+ @Value3 + ' ORDER BY 1 DESC';
exec sp_executesql @query, N' '
END
END
END
用户可以发送1到3个值,因为我有参数@cant
,此代码有效,但我想知道是否有更好的方法来执行此操作或如何改进此存储过程。
答案 0 :(得分:0)
如果你需要在SP而不是客户端进行,我认为你有什么用。我可能会将查询初始化为来自TBL_Folio"的选择*。然后在每个if之后附加LIKES。我也会提醒您不要使用SELECT *,这样如果某个字段被添加到表中,您的客户端就不会爆炸。
如果您需要检查可变数量的字段而不是最多3个字段,则可以执行表值参数并通过循环来构建查询。这是一个例子:
ALTER PROCEDURE [dbo].[GetFilteredInvoices]
@FilterColumns ColumnValueType READONLY
AS
BEGIN
SET NOCOUNT ON;
declare @columnName varchar(50), @columnValue varchar(MAX), @query nvarchar(MAX), @count int
set @query='SELECT InvoiceNumber, InvoiceDate, Customer from Invoices '
set @count=0
set @columnName=''
while exists(select * from @FilterColumns where ColumnName>@ColumnName)
begin
set @columnName=(select min(ColumnName) from @FilterColumns where ColumnName>@columnName)
if @count=0
set @query=@query+'WHERE '
else
set @query=@query+'AND '
set @query=@query+ (select ColumnName+' Like ''%'+ColumnValue+'%'' ' from @filterColumns where ColumnName=@columnName)
set @count=@count+1
end
exec sp_executesql @query
END
以下是我使用的表格类型:
CREATE TYPE [dbo].[ColumnValueType] AS TABLE(
[ColumnName] [varchar](50) NULL,
[ColumnValue] [varchar](max) NULL
)
GO
现在,这将使用任意数量的列和值来应用过滤器。
以下是对该过程的示例调用:
DECLARE @RC int
DECLARE @FilterColumns [dbo].[ColumnValueType]
insert into @filterColumns
Values('InvoiceNumber','345')
,('Customer','67')
EXECUTE @RC = [dbo].[GetFilteredInvoices]
@FilterColumns
答案 1 :(得分:0)
我认为您可以通过删除@cant
参数来改进处理输入参数的方式。您还可以在不处理仅设置@Column2
和@Value2
或仅设置@Column3
和@Value3
的情况下,改进构建条件的方式(也许在您的情况下不需要,但处理这些类型的场景仍然是一种很好的做法)
CREATE PROCEDURE SP_Select_TBL_Folio
@Column1 NVARCHAR(50) = NULL,
@Value1 NVARCHAR(50) = NULL,
@Column2 NVARCHAR(50) = NULL,
@Value2 NVARCHAR(50) = NULL,
@Column3 NVARCHAR(50) = NULL,
@Value3 NVARCHAR(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE
@P1 NVARCHAR(500),
@P2 NVARCHAR(500),
@P3 NVARCHAR(500),
@SQL NVARCHAR(MAX)
IF (@Column1 IS NULL OR @Column1 = '') AND (@Value1 IS NULL OR @Value1 = '')
BEGIN
-- This will build up dynamic SQL to always select records even if @Column1
-- and @Value1 is not set. This obvisously all depends on your requirements
-- and if you still need to select records if the parameters are not set, otherwise
-- it can be changed to ' WHERE ThePrimaryKeyColumn = 0'
SET @P1 = ' WHERE ThePrimaryKeyColumn > 0'
END
ELSE
BEGIN
SET @P1 = 'WHERE ' + @Column1 + ' LIKE ' + '''' + @Value1 + ''''
END
IF (@Column2 IS NULL OR @Column2 = '') AND (@Value2 IS NULL OR @Value2 = '')
BEGIN
SET @P2 = ''
END
ELSE
BEGIN
SET @P2 = ' AND ' + @Column2 + ' LIKE ' + '''' + @Value2 + ''''
END
IF (@Column3 IS NULL OR @Column3 = '') AND (@Value3 IS NULL OR @Value3 = '')
BEGIN
SET @P3 = ''
END
ELSE
BEGIN
SET @P3 = ' AND ' + @Column3 + ' LIKE ' + '''' + @Value3 + ''''
END
SET @SQL = 'SELECT * FROM TBL_Folio
[P1]
[P2]
[P3]'
-- Here we set all the conditions
SET @SQL = REPLACE(@SQL, '[P1]', @P1);
SET @SQL = REPLACE(@SQL, '[P2]', @P2);
SET @SQL = REPLACE(@SQL, '[P3]', @P3);
-- This will be replaced by EXEC(@SQL)
PRINT @SQL
END
所以现在你可以执行
EXEC SP_Select_TBL_Folio
会给你
SELECT * FROM TBL_Folio
WHERE ThePrimaryKeyColumn > 0
或者你可以执行
EXEC SP_Select_TBL_Folio 'Column1','Value1'
会给你
SELECT * FROM TBL_Folio
WHERE Column1 LIKE 'Value1'
或者你可以执行
EXEC SP_Select_TBL_Folio NULL,NULL,'Column2','Value2'
会给你
SELECT * FROM TBL_Folio
WHERE ThePrimaryKeyColumn > 0
AND Column2 LIKE 'Value2'
我不打算列出所有的排列,我相信你明白我的观点。