澄清 - 使用更新SQL

时间:2011-08-23 14:43:21

标签: tsql sql-update

我的存储过程如下所示。当我跑步时,它会失败。当我试图更新例如AGENT STATE语法时,我已经缩小了它的范围。 WHEN PropertyDefinitionID = @passStatePropertyDefID那么@passState - 代理状态

ALTER procedure [dbo].[usp_UpdateProfile] 
    @passCompanyName varchar(100),
    @passFName varchar(50),
    @passLName varchar(50),
    @passEmail varchar(50),
    @passStreet varchar(50),
    @passCity varchar(50),
    @passState int,
    @passZip varchar(10),
    @passPhone varchar(15),
    @passUserID int
As
Begin
    Declare @passCompanyNamePropertyDefID int 
    Declare @passFNamePropertyDefID int 
    Declare @passLNamePropertyDefID int 
    Declare @passEmailPropertyDefID int
    Declare @passStreetPropertyDefID int
    Declare @passCityPropertyDefID int
    Declare @passStatePropertyDefID int
    Declare @passPostalPropertyDefID int
    Declare @passPhonePropertyDefID int
    Declare @passACURefID int

    Set @passCompanyNamePropertyDefID = 62 -- Local PropertyDefinitionID from server : Agent Company Name
    Set @passFNamePropertyDefID = 61 -- Local PropertyDefinitionID from server : Agent First Name
    Set @passLNamePropertyDefID = 63 -- Local PropertyDefinitionID from server : Agent Last Name
    Set @passEmailPropertyDefID = 64 -- Local PropertyDefinitionID from server : Agent Email    
    Set @passStreetPropertyDefID = 65 -- Local PropertyDefinitionID from server : Agent Street
    Set @passCityPropertyDefID = 66 -- Local PropertyDefinitionID from server : Agent City
    Set @passStatePropertyDefID = 72 -- Local PropertyDefinitionID from server : Agent State
    Set @passPostalPropertyDefID = 67 -- Local PropertyDefinitionID from server : Agent State
    Set @passPhonePropertyDefID = 68 -- Local PropertyDefinitionID from server: Agent Telephone

    If(Exists(Select UserID From AgentCompanyUser Where UserID = @passUserID))
    Begin
        -- Modify First Name and Last Name in AgentCompanyUser table --
        Update AgentCompanyUser Set Agent_FirstName = @passFName, Agent_LastName = @passLName Where UserID = @passUserID        
    End

    -- Modify Email Address in dnn_Users table --
    Update dnn_Users Set Email = @passEmail Where UserID = @passUserID

    -- Retreive ACU_RefID from AgentCompanyUser table --
    Set @passACURefID = (Select ACU_RefID from AgentCompanyUser Where UserID = @passUserID) 

    -- UPDATE COMPANY WITH AGENT - AGENT PROFILE SECTION
    Update dnn_UserProfile  
    Set PropertyValue = CASE WHEN PropertyDefinitionID = @passFNamePropertyDefID THEN @passFName -- Agent First Name
                            WHEN PropertyDefinitionID = @passLNamePropertyDefID THEN @passLName -- Agent Last Name
                            WHEN PropertyDefinitionID = @passEmailPropertyDefID THEN @passEmail -- Agent Email
                            WHEN PropertyDefinitionID = @passStreetPropertyDefID THEN @passStreet -- Agent Street
                            WHEN PropertyDefinitionID = @passCityPropertyDefID THEN @passCity -- Agent City
                            WHEN PropertyDefinitionID = @passStatePropertyDefID THEN @passState -- Agent State
                            WHEN PropertyDefinitionID = @passPostalPropertyDefID THEN @passZip -- Agent Postal
                            WHEN PropertyDefinitionID = @passPhonePropertyDefID THEN @passPhone -- Agent Phone
                        END
    WHERE PropertyDefinitionID IN (@passFNamePropertyDefID, @passLNamePropertyDefID, @passEmailPropertyDefID, @passStreetPropertyDefID, @passCityPropertyDefID, @passStatePropertyDefID, @passPostalPropertyDefID, @passPhonePropertyDefID) 
        AND UserID IN (
        SELECT B.UserID 
        FROM CompanyAuthorizeAgent AS B
            INNER JOIN AgentCompanyUser AS A ON A.ACU_RefID = B.FK_acu_RefID 
        WHERE A.ACU_RefID = @passACURefID )
End 

但是如果修改代码来分隔导致我问题的代码。有用。下面的修改代码,你会看到我创建了另一个更新:

ALTER procedure [dbo].[usp_UpdateProfile] 
    @passCompanyName varchar(100),
    @passFName varchar(50),
    @passLName varchar(50),
    @passEmail varchar(50),
    @passStreet varchar(50),
    @passCity varchar(50),
    @passState int,
    @passZip varchar(10),
    @passPhone varchar(15),
    @passUserID int
As
Begin
    Declare @passCompanyNamePropertyDefID int 
    Declare @passFNamePropertyDefID int 
    Declare @passLNamePropertyDefID int 
    Declare @passEmailPropertyDefID int
    Declare @passStreetPropertyDefID int
    Declare @passCityPropertyDefID int
    Declare @passStatePropertyDefID int
    Declare @passPostalPropertyDefID int
    Declare @passPhonePropertyDefID int
    Declare @passACURefID int

    Set @passCompanyNamePropertyDefID = 62 -- Local PropertyDefinitionID from server : Agent Company Name
    Set @passFNamePropertyDefID = 61 -- Local PropertyDefinitionID from server : Agent First Name
    Set @passLNamePropertyDefID = 63 -- Local PropertyDefinitionID from server : Agent Last Name
    Set @passEmailPropertyDefID = 64 -- Local PropertyDefinitionID from server : Agent Email    
    Set @passStreetPropertyDefID = 65 -- Local PropertyDefinitionID from server : Agent Street
    Set @passCityPropertyDefID = 66 -- Local PropertyDefinitionID from server : Agent City
    Set @passStatePropertyDefID = 72 -- Local PropertyDefinitionID from server : Agent State
    Set @passPostalPropertyDefID = 67 -- Local PropertyDefinitionID from server : Agent State
    Set @passPhonePropertyDefID = 68 -- Local PropertyDefinitionID from server: Agent Telephone

    If(Exists(Select UserID From AgentCompanyUser Where UserID = @passUserID))
    Begin
        -- Modify First Name and Last Name in AgentCompanyUser table --
        Update AgentCompanyUser Set Agent_FirstName = @passFName, Agent_LastName = @passLName Where UserID = @passUserID        
    End

    -- Modify Email Address in dnn_Users table --
    Update dnn_Users Set Email = @passEmail Where UserID = @passUserID

    -- Retreive ACU_RefID from AgentCompanyUser table --
    Set @passACURefID = (Select ACU_RefID from AgentCompanyUser Where UserID = @passUserID) 

    -- UPDATE COMPANY WITH AGENT - AGENT PROFILE SECTION
    Update dnn_UserProfile  
    Set PropertyValue = CASE WHEN PropertyDefinitionID = @passFNamePropertyDefID THEN @passFName -- Agent First Name
                            WHEN PropertyDefinitionID = @passLNamePropertyDefID THEN @passLName -- Agent Last Name
                            WHEN PropertyDefinitionID = @passEmailPropertyDefID THEN @passEmail -- Agent Email
                            WHEN PropertyDefinitionID = @passStreetPropertyDefID THEN @passStreet -- Agent Street
                            WHEN PropertyDefinitionID = @passCityPropertyDefID THEN @passCity -- Agent City
                            WHEN PropertyDefinitionID = @passPostalPropertyDefID THEN @passZip -- Agent Postal
                            WHEN PropertyDefinitionID = @passPhonePropertyDefID THEN @passPhone -- Agent Phone
                        END
    WHERE PropertyDefinitionID IN (@passFNamePropertyDefID, @passLNamePropertyDefID, @passEmailPropertyDefID, @passStreetPropertyDefID, @passCityPropertyDefID, @passPostalPropertyDefID, @passPhonePropertyDefID)  
        AND UserID IN (
        SELECT B.UserID 
        FROM CompanyAuthorizeAgent AS B
            INNER JOIN AgentCompanyUser AS A ON A.ACU_RefID = B.FK_acu_RefID 
        WHERE A.ACU_RefID = @passACURefID )

    -- UPDATE COMPANY WITH AGENT - AGENT PROFILE SECTION (Add 2nd Update)
    Update dnn_UserProfile  
    Set PropertyValue = CASE WHEN PropertyDefinitionID = @passStatePropertyDefID THEN @passState-- Agent State
                        END
    WHERE PropertyDefinitionID IN (@passStatePropertyDefID) 
        AND UserID IN (
        SELECT B.UserID 
        FROM CompanyAuthorizeAgent AS B
            INNER JOIN AgentCompanyUser AS A ON A.ACU_RefID = B.FK_acu_RefID 
        WHERE A.ACU_RefID = @passACURefID )

End 

我的问题是为什么我必须创建另一个更新而不是使用我的原始代码才能使其工作?

提前致谢。

1 个答案:

答案 0 :(得分:5)

这是SQL Server中数据类型优先的经典案例。

Int始终具有比varchar更高的优先级。

您的第一个阻止

在第一个块的update语句中,即使CASE语句的一个结果表达式具有int数据类型(在本例中为@passState),并且CASE语句的其余结果表达式求值为varchar数据类型,那么所有的结果表达式都应该是Int,因为Int具有比varchar更高的优先级。

但是,当CASE的其余结果表达式求值为varchar时,您将在第一个CASE结果表达式@passFName上获得语法错误,因为它期望为所有人设置int:

  

将varchar值 * *转换为数据列的语法错误   输入int。

你的第二个座位

在第二个块中,第一个更新语句具有CASE,其中所有result_expressions都评估为varchar。因此它期望varchar并且没有转换问题。

在第二个更新语句中,只有一个结果表达式求值为int(@passState)。因此它隐式地将int转换为varchar。

<强>解决方案

解决方案当然是使用CASE或CONVERT在第一个块的CASE语句中将@passState转换为varchar,如下所示。

// ......................
CASE WHEN (PropertyDefinitionID = @passFNamePropertyDefID) THEN @passFName -- Agent First Name
    WHEN PropertyDefinitionID = @passLNamePropertyDefID THEN @passLName -- Agent Last Name
    WHEN PropertyDefinitionID = @passEmailPropertyDefID THEN @passEmail -- Agent Email
    WHEN PropertyDefinitionID = @passStreetPropertyDefID THEN @passStreet -- Agent Street
    WHEN PropertyDefinitionID = @passCityPropertyDefID THEN @passCity -- Agent City
    WHEN PropertyDefinitionID = @passStatePropertyDefID THEN CONVERT(varchar(50), @passState) -- Agent State
    --WHEN PropertyDefinitionID = @passStatePropertyDefID THEN CAST(@passState as varchar(50)) -- Agent State
    WHEN PropertyDefinitionID = @passPostalPropertyDefID THEN @passZip -- Agent Postal
    WHEN PropertyDefinitionID = @passPhonePropertyDefID THEN @passPhone -- Agent Phone
END
// ........................

<强>参考文献:

Data Type Precedence

来自CAST statement的引用: *从result_expressions中的类型集和可选的else_result_expression返回最高优先级类型。有关更多信息,请参阅数据类型优先级(Transact-SQL)。*