db2 意外的标记“SELECT”SQL代码= -104,SQLSTATE=42601,驱动程序=3.69.66

57hvy0tb  于 2023-01-17  发布在  DB2
关注(0)|答案(1)|浏览(345)

我有一个存储过程,我需要将它从Sybase SQL转换为DB2 SQL。下面的代码是针对Sybase SQL的。

CREATE PROC TAS_TEST
(
    @LOGIN_ID VARCHAR(20),
    @NAME     VARCHAR(100),
    @C_NAME   VARCHAR(100),
    @USER     VARCHAR(20),
    @DEBUG    BIT_FLAG=0
)
AS
BEGIN

    DECLARE @TOKEN_EXPIRY_DATE DATETIME,
        @TOKEN VARCHAR(36),
        @ERR INT,
        @ERROR_MSG VARCHAR(200)
        
    SET @LOGIN_ID = LTRIM(RTRIM(@LOGIN_ID))
    
    IF @LOGIN_ID IS NULL
    BEGIN
        RAISEERROR 20000 'LOGIN ID IS MUST:[%1!]',@LOGIN_ID
        RETURN -1
    END
    IF @NAME IS NULL
    BEGIN
        RAISEERROR 20000 'NAME IS MUST:[%1!]',@NAME
        RETURN -1
    END
    IF @C_NAME IS NULL
    BEGIN
        RAISEERROR 20000 'C_NAME IS MUST:[%1!]',@C_NAME
        RETURN -1
    END
    IF @USER IS NULL
    BEGIN
        RAISEERROR 20000 'USER IS MUST:[%1!]',@USER
        RETURN -1
    END
    
    SELECT
        @TOKEN = TOKEN,
        @TOKEN_EXPIRY_DATE = TOKEN_EXPIRY_DATE
    FROM TOKEN_DETAILS
    WHERE
        LOGIN_ID = @LOGIN_ID and
        NAME = @NAME and
        C_NAME = @C_NAME
        
    
    IF(@TOKEN IS NULL)
    BEGIN
        IF @DEBUG = 1 BEGIN
            PRINT "No token exists"
        END
        
        SELECT @TOKEN = NEWID(1)
        SELECT @TOKEN_EXPIRY_DATE = DATEADD(HOUR,12,GETUTCDATE())
        
        INSERT INTO TOKEN_DETAILS(
            LOGIN_ID,
            TOKEN,
            NAME,
            C_NAME,
            TOKEN_EXPIRY_DATE,
            CREATED_DATE,
            CREATED_BY
        )VALUES(
            @LOGIN_ID,
            @TOKEN,
            @NAME,
            @C_NAME,
            @TOKEN_EXPIRY_DATE,
            GETUTCDATE(),
            @USER
        )
        IF(@@ERROR !=0 )
        BEGIN
            SELECT @ERROR_MSG = CONVERT(CHAR(26),GETDATE(),109)+
            " - Error while inserting - "+ CONVERT(VARCHAR,@@ERROR)
            RAISEERROR 30000 @ERROR_MSG
        RETURN -1
        END
    END
    
    ELSE IF(@TOKEN_EXPIRY_DATE < GETUTCDATE())
    BEGIN
        IF @DEBUG = 1 BEGIN
            PRINT "TOKEN EXPIRES"
        END
        
        SELECT @TOKEN = NEWID(1)
        SELECT @TOKEN_EXPIRY_DATE = DATEADD(HOUR,12,GETUTCDATE())
        
        UPDATE
            TOKEN_DETAILS
        SET
            TOKEN = @TOKEN,
            TOKEN_EXPIRY_DATE = @TOKEN_EXPIRY_DATE
        WHERE
            LOGIN_ID = @LOGIN_ID and
            NAME = @NAME and
            C_NAME = @C_NAME
            
        IF(@@ERROR !=0 )
        BEGIN
            SELECT @ERROR_MSG = CONVERT(CHAR(26),GETDATE(),109)+
            " - Error while UPDATING - "+ CONVERT(VARCHAR,@@ERROR)
            RAISEERROR 30000 @ERROR_MSG
        RETURN -1
        END
    END
    
    ELSE IF @DEBUG = 1 
    BEGIN
        PRINT "TOKEN EXIST"
    END
    SELECT @TOKEN AS 'TOKEN', @TOKEN_EXPIRY_DATE AS 'TOKEN_EXPIRY_DATE'
END
GO

GRANT EXECUTE TAS_TEST TO ADMIN
GO

这是我为上述Sybase SQL编写的转换后的DB2 SQL。

CREATE OR REPLACE PROCEDURE TAS_TEST
(
    LOGIN_ID VARCHAR(20),
    NAME      VARCHAR(100),
    C_NAME    VARCHAR(100),
    USER      VARCHAR(20),
    DEBUG     SMALLINT DEFAULT 0
)

LANGUAGE SQL

BEGIN

DECLARE TOKEN_EXPIRY_DATE TIMESTAMP;
DECLARE TOKEN VARCHAR(36);
DECLARE ERR INT;
DECLARE ERROR_MSG VARCHAR(200);

SET LOGIN_ID = TRIM(LOGIN_ID);

IF LOGIN_ID IS NULL THEN
    SIGNAL SQLSTATE VALUE '20000'
    SET MESSAGE_TEXT = 'LOGIN ID IS MUST:';
END IF;
IF NAME IS NULL THEN
    SIGNAL SQLSTATE VALUE '20000'
    SET MESSAGE_TEXT = 'NAME IS MUST:';
END IF;
IF C_NAME IS NULL THEN
    SIGNAL SQLSTATE VALUE '20000'
    SET MESSAGE_TEXT = 'C_NAME IS MUST:';
END IF;
IF USER IS NULL THEN
    SIGNAL SQLSTATE VALUE '20000'
    SET MESSAGE_TEXT = 'USER IS MUST:';
END IF;

SELECT
    TOKEN = TOKEN,
    TOKEN_EXPIRY_DATE = TOKEN_EXPIRY_DATE
FROM TOKEN_DETAILS
WHERE
    LOGIN_ID = LOGIN_ID and
    NAME = NAME and
    C_NAME = C_NAME;
    
IF(TOKEN IS NULL) THEN
BEGIN
    IF DEBUG = 1 THEN
        PRINT 'No token exists';
    END IF;
    
    SELECT TOKEN = GENERATE_UNIQUE(1) FROM SYSIBM.SYSDUMMY1;
    SELECT TOKEN_EXPIRY_DATE = TIMESTAMPADD(CURRENT_TIMESTAMP) FROM SYSIBM.SYSDUMMY1;
    
    INSERT INTO TOKEN_DETAILS(
        LOGIN_ID,
        TOKEN,
        NAME,
        C_NAME,
        TOKEN_EXPIRY_DATE,
        CREATED_DATE,
        CREATED_BY
    )VALUES(
        LOGIN_ID,
        TOKEN,
        NAME,
        C_NAME,
        TOKEN_EXPIRY_DATE,
        CURRENT_TIMESTAMP,
        USER
    );
END;
END IF;

IF(TOKEN_EXPIRY_DATE < CURRENT_TIMESTAMP)
BEGIN
    IF DEBUG = 1 THEN
        PRINT "TOKEN EXPIRES, UPDATING";
    END IF;
    
    SELECT TOKEN = GENERATE_UNIQUE(1) FROM SYSIBM.SYSDUMMY1;
    SELECT TOKEN_EXPIRY_DATE = TIMESTAMPADD(CURRENT_TIMESTAMP) FROM SYSIBM.SYSDUMMY1;
    
    UPDATE
        TOKEN_DETAILS
    SET
        TOKEN = TOKEN,
        TOKEN_EXPIRY_DATE = TOKEN_EXPIRY_DATE
    WHERE
        LOGIN_ID = LOGIN_ID and
        NAME = NAME and
        C_NAME = C_NAME;
END;
END IF;

IF (DEBUG = 1) THEN 
BEGIN
    PRINT "TOKEN EXIST";
END;
END IF;
SELECT TOKEN, TOKEN_EXPIRY_DATE FROM SYSIBM.SYSDUMMY1;
END;

GRANT EXECUTE TAS_TEST TO ADMIN;

在运行上面的db2查询时,我得到了这个错误。
[42601][-104]在“"后面找到意外的标记“SELECT”。预期标记可能包括“END IF”.. SQL代码= -104,SQLSTATE=42601,DRIVER=3.69.66
有没有人能帮我弄清楚我哪里做错了,这会有很大的帮助。

f87krz0w

f87krz0w1#

您的代码中有多个问题将阻止在Db2上编译。
考虑接受一些关于ANSISQLPL(Db2-LUW使用的语法)的教育。
了解IBM在Db2-LUW服务器的samples目录、Db2-LUW知识中心和github上提供的许多示例SQL PL过程。
让有能力或经验丰富的SQL PL开发人员审查您的代码。
一些建议:

  • PRINT语句在ANSI SQL PL中无效。对于Db2-LUW,许多人将调试call dbms_output.put_line('some message');set serveroutput on一起用于会话。
  • 使用SET语句分配函数中的变量。示例:SET v_token = GENERATE_UNIQUE();
  • 只有在需要块特定的异常处理或条件处理时才使用内部BEGIN .. END块。不必仅为了分隔IF内的一组语句而使用BEGIN ... END块。
  • 不要使用保留字作为变量名或列名(如USER
  • 考虑对参数和局部变量使用命名约定。命名约定可能使用一些指示符来指示名称是局部的v_*,或者指示名称是例程p_*的参数。
  • 在例程中,使用SELECT ... INTO ...从单例选择中分配变量。
  • 要为结果集列设置别名,请使用"colName AS colAlias"语法
  • 若要返回结果集,请在签名中显式指定结果集,并在末尾声明和打开游标。您的SELECT TOKEN, TOKEN_EXPIRY_DATE FROM SYSIBM.SYSDUMMY1;行无效。
  • Db2 GENERATE_UNIQUE()函数不接受参数。
  • 考虑使用CURRENT TIMESTAMP + 12 HOURS代替TIMESTAMPADD。
  • 若要测试查询后是否缺少行,请显式测试SQLCODE 100或使用条件处理程序。
  • 考虑将upsert作为单个MERGE语句的一部分来执行,这样可以使代码更清晰,并简化错误检测和恢复。

相关问题