存储过程不返回结果,但查询返回

Posted

技术标签:

【中文标题】存储过程不返回结果,但查询返回【英文标题】:stored proc returns no results, but query does 【发布时间】:2010-08-27 23:01:51 【问题描述】:

我刚刚设法启用全文搜索,以便更轻松地在我的系统中搜索产品。但是,我使用的是由其他人构建的 sp,它没有为“值班电话”返回任何结果。实际上,我正在搜索系统中的产品“使命召唤”。如果我输入“使命召唤”,它确实会返回结果,但删除一个单词并翻转剩余的单词不会给出结果。代码如下:

USE [storeboard]
GO
/****** Object:  StoredProcedure [sbuser].[sp_ProductSearch]    Script Date: 08/26/2010 05:57:20 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [sbuser].[sp_ProductSearch]
    @StoreItemID bigint = null,
    @StoreMemberID bigint = null,
    @ProductName varchar(50) = null,
    @ProductDesc varchar(1000) = null,
    @ItemPrice float = null,
    @Active bit = null,
    @Deleted bit = null,
    @CreateDate datetime = null,
    @ShipWeight float = null,
    @TaxExempt bit = null,
    @ShipCost float = null,
    @Keywords varchar(1000) = null,
    @PG int = 1,
    @ROWCT numeric(18,2) = 1,
    @COLCT numeric(18,2) = 1,
    @MODE varchar(50),
    @StoreItemCatID bigint = null,
    @SearchStr varchar(100) = null

AS


IF @MODE = 'S1'    
    BEGIN
        SELECT
        StoreItemID,
        ProductName,
        ItemPrice,
        PG,
        MAXPG,
        TOTALRECS,
        CoverImg,
        StoreItemCatID,
        Active
        FROM sbuser.tf_ProductSearch(@PG,@ROWCT,@COLCT,@StoreItemCatID,@SearchStr)
    END

代码指的是 tf_productSearch 是这样的:

USE [storeboard]
GO
/****** Object:  UserDefinedFunction [sbuser].[tf_ProductSearch]    Script Date: 08/26/2010 05:46:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [sbuser].[tf_ProductSearch] (
    @PG int,
    @ROWCT numeric(18,2),
    @COLCT numeric(18,2),
    @StoreItemCatID bigint,
    @SearchStr varchar(100) = null)

RETURNS @OUT TABLE (
    StoreItemID bigint,
    ProductName varchar(50),
    ProductDesc varchar(1000),
    ItemPrice float,
    Active bit,
    CreateDate datetime,
    ShipWeight float,
    TaxExempt bit,
    ShipCost float,
    Keywords varchar(1000),
    PG int,
    MAXPG INT,
    TOTALRECS INT,
    CoverImg varchar(50),
    StoreItemCatID bigint )

AS

BEGIN

        DECLARE @START numeric(18,2);
        DECLARE @END numeric(18,2);
        DECLARE @SIZE numeric(18,2);
        DECLARE @MAXPG numeric(18,2);
        DECLARE @TOTALRECS numeric(18,2);
        DECLARE @TOTALRECS_INT int;
        DECLARE @MAXPG_INT int;
        DECLARE @TOTALRECS_REMAINDER numeric(18,2);
        SET @SIZE = @ROWCT * @COLCT
        SET @Start = (((@PG - 1) * @Size) + 1)
        SET @END = (@START + @SIZE - 1)


        DECLARE @TMP1 TABLE (
        TmpID bigint identity(1,1) primary key,
        StoreItemID bigint,
        ProductName varchar(50),
        ProductDesc varchar(1000),
        ItemPrice float,
        Active bit,
        CreateDate datetime,
        ShipWeight float,
        TaxExempt bit,
        ShipCost float,
        Keywords varchar(1000),
        CoverImg varchar(50),
        StoreItemCatID bigint )


        IF @StoreItemCatID IS NULL
            BEGIN
                INSERT INTO @TMP1 
                SELECT
                a.StoreItemID,
                a.ProductName,
                a.ProductDesc,
                a.ItemPrice,
                a.Active,
                a.CreateDate,
                a.ShipWeight,
                a.TaxExempt,
                a.ShipCost,
                a.Keywords,
                sbuser.sf_StoreItemCoverImg(a.StoreItemID) AS CoverImg,
                a.StoreItemCatID
                FROM sbuser.StoreItem a
                WHERE FREETEXT (a.ProductName, @SearchStr)
                AND Deleted = 0    
                AND Active = 1
                ORDER BY a.ProductName 
            END
        ELSE

            BEGIN
                INSERT INTO @TMP1 
                SELECT
                a.StoreItemID,
                a.ProductName,
                a.ProductDesc,
                a.ItemPrice,
                a.Active,
                a.CreateDate,
                a.ShipWeight,
                a.TaxExempt,
                a.ShipCost,
                a.Keywords,
                sbuser.sf_StoreItemCoverImg(a.StoreItemID) AS CoverImg,
                a.StoreItemCatID
                FROM sbuser.StoreItem a
                WHERE FREETEXT (a.ProductName, @SearchStr)
                AND a.StoreItemCatID = @StoreItemCatID
                AND a.Deleted = 0    
                AND a.Active = 1
                OR a.StoreItemCatID IN (SELECT StoreItemCatID FROM StoreItemCat WHERE ParentID = @StoreItemCatID)
                AND FREETEXT (a.ProductName, @SearchStr)
                AND a.Deleted = 0    
                AND a.Active = 1
                ORDER BY a.ProductName
            END



        SELECT @TOTALRECS = MAX(TMPID) FROM @TMP1
        SELECT @MAXPG = @TOTALRECS / @SIZE
        SET @TOTALRECS_REMAINDER = @TOTALRECS % @SIZE

        SET @MAXPG_INT = CAST(@MAXPG AS INT)
        SET @TOTALRECS_INT = CAST(@TOTALRECS AS INT)


        IF @TOTALRECS_REMAINDER > 0 
            BEGIN
                SET @MAXPG_INT = @MAXPG_INT + 1
            END        



        INSERT INTO @OUT
        SELECT 
            StoreItemID,
            ProductName,
            ProductDesc,
            ItemPrice,
            Active,
            CreateDate,
            ShipWeight,
            TaxExempt,
            ShipCost,
            Keywords,
            @PG,
            @MAXPG_INT,
            @TOTALRECS_INT,
            CoverImg,
            StoreItemCatID
            FROM @TMP1
            WHERE (TmpID >= @Start) AND (TmpID <= @END)        

    RETURN


END

在经典 ASP 网页中调用,代码如下:

Dim ProductCat
Dim paryProducts
Dim ProdMaxPG
Dim pstrProductList

Const C_PRODUCTS_FE_PRODUCTROWCOUNT = 4
Const C_PRODUCTS_FE_PRODUCTCOLCOUNT = 5
SearchStr = "duty call"
StoreItemCatID = ""

cData.SQL = "sp_ProductSearch " _
          & cData.ProcFld("MODE","S1",2,True) _
          & cData.ProcFld("PG",PG,0,True) _
          & cData.ProcFld("ROWCT",C_PRODUCTS_FE_PRODUCTROWCOUNT,0,True) _
          & cData.ProcFld("COLCT",C_PRODUCTS_FE_PRODUCTCOLCOUNT,0,True) _
          & cData.ProcFld("SearchStr",SearchStr,2,True) _
          & cData.ProcFld("StoreItemCatID",StoreItemCatID,0,False)
paryProducts = cData.RSArray()

但是,这些脚本不返回任何结果。但是,直接在sql-server的查询窗口中输入以下代码:

USE storeboard
GO
DECLARE @SearchStr varchar(50)
SET @SearchStr = 'duty call';
SELECT
                a.StoreItemID,
                a.ProductName,
                a.ProductDesc,
                a.ItemPrice,
                a.Active,
                a.CreateDate,
                a.ShipWeight,
                a.TaxExempt,
                a.ShipCost,
                a.Keywords,
                a.StoreItemCatID
                FROM sbuser.StoreItem a
                WHERE FREETEXT (a.ProductName, @SearchStr)
                AND a.Deleted = 0    
                AND a.Active = 1
                ORDER BY a.ProductName

确实返回结果。我在这里不合群,想知道你们中的一位经验丰富的程序员是否会在这里看到明显错误的地方。如果你们能提供任何帮助,我们将不胜感激。

非常感谢,

保罗

【问题讨论】:

你能不能试着把它剪成一个更小的例子 - 这里有很多东西要通读,我认为很多人不会坚持下去。 我不确定是否可以缩小它的大小,因为所有这些代码都是相关的。 【参考方案1】:

好的,这不是重写,因为我没有时间也没有要求来满足您的需求,但这里有一些提示...

    如果你不需要表值函数,就去掉它;将该逻辑移到您的存储过程中。

    摆脱您的IF @StoreCatItem IS NULL 语句并在您的WHERE 子句中使用类似WHERE (@StoreCatItem IS NULL OR a.StoreItemCatID = @StoreCatItem) 的结构来合并为1 个SELECT 语句。如果您的意图是鼓励适当的索引使用,请在查询末尾添加 OPTION(RECOMPILE) 提示,而不是复制 sql。

    我看到您正在存储过程中进行分页。临时表是一个好主意,但更改它的定义和您的插入查询以仅包含以正确方式排序的完整结果集的主键值加上您的 IDENTITY 列,但您很可能只需要一个 INT 列,而不是 BIGINT,并不是说它在临时表上很重要。插入表变量的第一个查询是您使用 WHERE 条件过滤的位置。对您的每个标准都使用上面提到的构造。 WHERE (@StoreCatItem IS NULL OR a.StoreItemCatID = @StoreCatItem OR a.StoreItemCatID IN ( SELECT x.StoreItemCatID FROM StoreItemCat x WHERE x.ParentID = @StoreItemCatID)) AND FREETEXT (a.ProductName, @SearchStr) AND a.StoreItemCatID = @StoreItemCatID AND a.Deleted = 0 AND a.Active = 1

    返回记录的最终选择语句应该再次在表变量中的键和真实数据之间执行简单的 INNER JOIN;您可以在此处选择所需的所有真实字段,并且无需再次重复您的条件,因为连接会过滤您的结果。

    如果您只是在学习,迭代创建是无可替代的。从您所知道的有效的开始并在此基础上进行构建。

享受吧!

【讨论】:

在您的建议下,我解决了这个问题。非常感谢 Tahbaza【参考方案2】:

tf_ProductSearch 函数中 WHERE 子句的元素在 ELSE 部分重复/不正确地关联逻辑(它与您的工作查询不匹配)。这可能是问题所在。

【讨论】:

好的,那么你将如何重写这个,因为这对我来说都是全新的......请帮我解决这个问题...... 重写是另一回事(例如,我不知道为什么你有一个表值函数,但我也不熟悉你的要求......)通过自己测试您的 tf_ProductSearch 函数来调试它。将您的工作查询放入您的函数中,暂时注释掉 /* */ 不起作用的查询。当它起作用时,开始比较差异并添加你需要的东西。祝你好运! 我听到了,虽然我有 2 周的 t-sql 经验。我真的很感激看到你会如何写这个。请告诉我,我在这里很绝望!

以上是关于存储过程不返回结果,但查询返回的主要内容,如果未能解决你的问题,请参考以下文章

将存储过程中选择查询的结果返回到列表

oracle 存储过程,数据处理并返回结果集问题

sqlserver 存储过程 返回结果集的 例子

传递参数以返回存储过程的复杂结果

MYSQL的存储过程如何返回查询到的行数据?

ORACLE 存储过程怎么返回临时表结果集