动态执行SQL语句,“SELECT TOP N *”语句中“N”不能为变量的解决方案

来源:互联网 发布:外包美工主要干嘛 编辑:程序博客网 时间:2024/06/05 20:37

 前段时间,想写一个返回指定数量记录的PROCEDURE,代码如下:

 

CREATE PROCEDURE GetSomeArticles

@cnt int = 1

AS

SELECT TOP @cnt * FROM Articles

 

结果发现无法运行,始终有问题,百思不得其解,后来询问了一下老师才知道,SELECT TOP N这里的参数N只能为常量,不能为变量。

 

如果在程序中直接定义SQL语句,然后执行,是可以达到预期效果的:

  1. int cnt = 10;
  2. string strSQL = "SELECT TOP " + cnt.ToString() + " * FROM Articles";
  3. //我自己写的一个应用了工厂设计模式的操作数据库的类
  4. //封装了N多操作数据库的方法
  5. //并且实现了数据库无关性
  6. //即可以用同样的代码来操作Access、MS SQL SERVER、MySQL
  7. //理论上也可以实现操作Oracle,只是没用过它,所以暂时没实现,呵呵
  8. CommDB db = CreateDB.Create();
  9. //执行数据库操作,返回一个DataSet 
  10. DataSet ds = db.ExecSQL(strSQL);

但是我确实有这样的需要,想用存储过程来实现,这可怎么办呢?还好,有动态执行SQL这一说法(其实我也不知道这一说法是否准确,暂且这样称呼吧),于是我们可以这样写存储过程:

 

CREATE PROCEDURE GetSomeArticles

@cnt int = 1

AS

EXEC ("SELECT TOP " + @cnt + "  * FROM Articles")

 

这样就可以解决SELECT TOP N中那个N只能为常量的问题了^_^

 

另,在MySQL中要实现类似的功能,可以这样写:

 

DELIMITER $$

 

CREATE PROCEDURE `GetSomeArticles`(in cnt int)
BEGIN
    set @stmt = concat('SELECT * FROM Articles LIMIT 0, ?');
    prepare s1 from @stmt;
    set @s1 = cnt;
    execute s1 using @s1;
    deallocate prepare s1;
END$$

DELIMITER ;