日期:2014-05-18  浏览次数:20568 次

疑难问题,困扰了几天了。关于在存储过程中灵活使用变量的问题。
表结构:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[t_student](
[id] [int] NOT NULL,
[name] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
[age] [int] NULL,
[address] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,
 CONSTRAINT [PK_t_student] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

数据:
INSERT INTO [dbo].[t_student] ([id],[name],[age],[address]) VALUES(1,'tom',12,'北京市海淀区')
INSERT INTO [dbo].[t_student] ([id],[name],[age],[address]) VALUES(2,'jim',40,'上海')
INSERT INTO [dbo].[t_student] ([id],[name],[age],[address]) VALUES(3,'roles',10,'beijing')

需求:从数据库中读取数据的时候id必输,其他字段名称可以不输入。

一般的情况下在代码拼sql语句取得数据的话,可以灵活的实现:  
string strsql = " select * from t_student where id = ";
if(id == null )
{
return false;
}
else
{
strsql = strsql + id;
}

if(name != null)
 strsql = strsql + " AND name= '" + name + "'" ;

if(age != null)
 strsql = strsql + " and age = " + age ;
 
if(address != null)
 strsql = strsql + " and address = '" + address + "'" ;
 有了sql语句后面就可以使用ado.net中的对象把数据取出来了。
 
 
 现在我想使用存储过程完成这个功能,这个存储过程应该怎么写呢?


------解决方案--------------------
还是一样的思路嘛,只是语法不一样而已,你查查语法应该就可以写的了,动动手啊~
------解决方案--------------------
前一个贴子已经回你了.

很简单.我假设,你存储过程的两个参数为 @p1,@p2 

那么依具你存储过程中的写法,也有不同的写法. 


SQL code
SQL code--1,若是采用动态语句
declare @sql varchar(1000)
set @sql='select * from tb where 1=1 '
if @p1 is not null
  set @sql=@sql + ' and field1=' + @p1
if @p2 is not null
  set @sql=@sql + ' and field2=' + @p2

--2,若是采用的非动态语句

select * from tb 
  where field1=case when @p1 is null then field1 else @p1 end
       and field2=case when @p2 is null then field2 else @p2 end

------解决方案--------------------
如果c#实现的话, 建议, 
1,采用存储过程来处理
2,采用带参数的SQL语句来处理

如果采用存储过程,那么参数如何处理,我上面说了,
如果采用带参数的SQL语句,那么写法写类似

C# code
string sql=" select * from tb where field1=isnull(@p1,field1) and field2=isnull(@p2,field2)";
SqlParameters parameters= new .....();
parameters.Add(....)
..
SqlHelper.ExeNo....(sql,parameters,....);

------解决方案--------------------
我倒建议使用邦定变量

strsql="select * from t where 1=1 and id=@p"

根据数据库执行SQL的原理,这个最适合在多客户端频繁查询同一数据表的情况,因为忙得时候DBMS会省去解析过程
------解决方案--------------------
我倒建议使用邦定变量

strsql="select * from t where 1=1 and id=@p"

根据数据库执行SQL的原理,这个最适合在多客户端频繁查询同一数据表的情况,因为忙得时候DBMS会省去解析过程

这样当@p为null时
执行的是 select * from t where id is null
而楼主的意图是当@p为null时
执行的是 select * from t --即不检索id=@p这个条件.

与楼主意图根本冲突.
为了所谓的性能,而满足不了业务要求, 即然不能完足业务要求,也即得出的结果不是业务所需的,那么即便提高了效率,也是没意义的.
------解决方案--------------------
SQL code

用动态SQL语句。

declare @sql varchar(8000)

set @sql =

------解决方案--------------------
set @sql = @sql + ' and id = ' + @id 

-->改为

set @sql = @sql + ' and id = ' + cast(@id as varchar(100))

------解决方案--------------------
set @sql = @sql + ' and age= ' + @age 
-->
set @sql = @sql + ' and age= ' + cast(@age as varchar(10))