当存在行时,SQL Server'='不返回任何行

时间:2015-02-22 05:55:01

标签: sql-server sql-server-2008 stored-procedures

我试图弄清楚为什么SQL Server存储过程为列存储了错误的ID值,这使得存储过程在存在两行时返回零行。

当在存储过程之外执行select语句时,我得到了我正在寻找的结果,但这是由另一个应用程序使用的,我不想硬编码select语句,我想使用存储过程因为该程序用于应用程序的许多部分。

IF OBJECT_ID('GET_ENABLE_OBJ_SP') IS NOT NULL
    DROP PROC GET_ENABLE_OBJ_SP
GO

CREATE PROC GET_ENABLE_OBJ_SP   
    @COURSE VARCHAR(10) = NULL,
    @OBJ    VARCHAR(10) = NULL,
    @DEPT_DES VARCHAR(10) = NULL
AS
BEGIN 
    DECLARE @COURSE_ID INT;
    DECLARE @OBJ_ID INT;
    DECLARE @DEPT_ID INT;

    IF EXISTS (SELECT DEPT_ID FROM DEPARTMENT 
               WHERE DEPT_DESIGNATOR = @DEPT_DES)
    BEGIN 
        SELECT @DEPT_ID = DEPT_ID 
        FROM DEPARTMENT 
        WHERE DEPT_DESIGNATOR = @DEPT_DES;
    END

    PRINT 'DEPARTMENT ID: ' + CONVERT(VARCHAR,@DEPT_ID);
    PRINT 'DEPT DESIGNAT: ' + @DEPT_DES;

    IF @COURSE IS NULL
        RAISERROR('MUST SUPPLY A COURSE DESIGNATOR', 11, 1);

    IF @OBJ IS NULL
        RAISERROR ('MUST SUPPLY AN OBJECTIVE DESIGNATOR', 11, 1);

    -- FIND THE COURSE
    IF EXISTS (SELECT COURSE_ID FROM COURSE 
               WHERE COURSE_DESIGNATOR = @COURSE AND DEPT_ID = @DEPT_ID)
    BEGIN 
        SELECT @COURSE_ID = COURSE_ID 
        FROM COURSE 
        WHERE COURSE_DESIGNATOR = @COURSE AND DEPT_ID = @DEPT_ID;
    END

    PRINT 'COURSE_ID:  ' + CONVERT(VARCHAR, @COURSE_ID);
    PRINT 'COURSE DES:  ' + @COURSE;

    IF @COURSE_ID IS NULL
        RAISERROR('COURSE DOES NOT EXISTS', 11, 1);

    IF EXISTS (SELECT CTO_ID FROM COURSE_TERMINAL_OBJECTIVE 
               WHERE COURSE_ID = @COURSE_ID)
    BEGIN 
        SELECT @OBJ_ID = CTO_ID 
        FROM COURSE_TERMINAL_OBJECTIVE 
        WHERE COURSE_ID = @COURSE_ID AND DEPT_ID = @DEPT_ID;
    END

    PRINT 'OBJECTIVE ID: ' + CONVERT(VARCHAR, @OBJ_ID);
    PRINT 'OBJ DESIGNAT: ' + @OBJ;

    IF @OBJ_ID IS NULL
        RAISERROR('OBJECTIVE IS INVALID OR DOES NOT EXIST', 11, 1);
    ELSE
        IF EXISTS (SELECT CEO_ID FROM COURSE_ENABLE_OBJECTIVE 
                   WHERE CTO_ID = @OBJ_ID AND COURSE_ID = @COURSE_ID)
        BEGIN 
            SELECT 
               E.CEO_DESIGNATOR, E.CEO_DESCRIPTION
            FROM 
               COURSE_ENABLE_OBJECTIVE E
            JOIN 
               COURSE_TERMINAL_OBJECTIVE T ON E.COURSE_ID = T.COURSE_ID 
                                           AND E.CTO_ID = T.CTO_ID
            WHERE 
               E.COURSE_ID = @COURSE_ID 
               AND T.CTO_ID = @OBJ_ID;
         END
END
GO

这是我用来调用它的执行语句,以及为所选“部门”和“课程”选择该表的所有值的语句

begin try
    exec GET_ENABLE_OBJ_SP '201', '1.0.0', 'CIS'
    EXEC GET_OBJECTIVES '201', 'CIS'

    SELECT * 
    FROM COURSE_TERMINAL_OBJECTIVE 
    WHERE COURSE_ID = 6

    SELECT * 
    FROM COURSE_ENABLE_OBJECTIVE 
    WHERE COURSE_ID = 6
end try
begin catch
    PRINT  'ERROR' + CONVERT(VARCHAR, ERROR_NUMBER());
    PRINT 'MESSAGE: ' + ERROR_MESSAGE();
end catch

我可以使用select语句返回所有值并对值进行硬编码但返回不属于的行,这里是返回值的屏幕截图和存储过程中的'print'语句。由于某种原因,当它应该为1时,它将@obj_id(CTO_ID)返回为4.我的目标是在下面的结果集中返回正确的CEO_ID列,其中CTO_ID = 1且COURSE_ID = 6.存储过程,正如您在消息中看到的那样,我将传入的指定符('1.0.0')标记为属于ID 4,从结果集中清楚地标记为ID 1而不是4,这会导致什么?

Result_Set.jpg

Messages.jpg

2 个答案:

答案 0 :(得分:2)

本声明

SELECT @OBJ_ID = CTO_ID 
FROM COURSE_TERMINAL_OBJECTIVE 
WHERE COURSE_ID = @COURSE_ID AND DEPT_ID = @DEPT_ID;

匹配COURSE_TERMINAL_OBJECTIVE表中的4行。如果你只想匹配CTO_ID = 1,那么你需要缩小你的WHERE子句。

应该是

SELECT @OBJ_ID = CTO_ID 
FROM COURSE_TERMINAL_OBJECTIVE 
WHERE COURSE_ID = @COURSE_ID AND DEPT_ID = @DEPT_ID 
  AND CTO_DESIGNATOR = @OBJ;

答案 1 :(得分:1)

我认为这就是原因:

SELECT 
  @OBJ_ID = CTO_ID 
FROM 
  COURSE_TERMINAL_OBJECTIVE 
WHERE
  COURSE_ID = @COURSE_ID AND
  DEPT_ID = @DEPT_ID;

你有4行有course_id 6和dept_id 1.结果是select中的最后一个id是保留在变量中的id。

也许你错过了cto_designator?或者如果你想拥有第一个,你应该选择前1 +订单来保证你真正需要的那个。

“if exists”也有相当奇怪的逻辑,你只有course_id,但你也是用dept_id获取的。