Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 泛型更新行存储过程_Sql Server_Sql Server 2008_Stored Procedures - Fatal编程技术网

Sql server 泛型更新行存储过程

Sql server 泛型更新行存储过程,sql-server,sql-server-2008,stored-procedures,Sql Server,Sql Server 2008,Stored Procedures,场景:Web应用程序,各种表格,每个表格可以从应用程序中的不同位置更新,但并非所有列都会一直更新 我需要一个给定表的通用存储过程,该存储过程可用于处理对行的更新。我想构建它,这样,如果我只更新几个列(可能有很多列),那么我只发送这些参数(减少数据库的负载,减少代码行,等等)。如果不存在任何参数,则不会更新列 目前,所有参数(例如,每列1个)默认为空。然后,如果该值为NULL,则该列不会得到更新。如果参数不为null,例如传递了值,则使用新值更新列 CREATE PROCEDURE [dbo].[

场景:Web应用程序,各种表格,每个表格可以从应用程序中的不同位置更新,但并非所有列都会一直更新

我需要一个给定表的通用存储过程,该存储过程可用于处理对行的更新。我想构建它,这样,如果我只更新几个列(可能有很多列),那么我只发送这些参数(减少数据库的负载,减少代码行,等等)。如果不存在任何参数,则不会更新列

目前,所有参数(例如,每列1个)默认为空。然后,如果该值为NULL,则该列不会得到更新。如果参数不为null,例如传递了值,则使用新值更新列

CREATE PROCEDURE [dbo].[bfsp_update_MEMBER]
(   
    @IN_id INT = NULL,
    @IN_orig_id INT = NULL,

    @IN_flags INT = NULL,
    @IN_member_flags INT = NULL,
    @IN_role_flags INT = NULL,
    @IN_validation_flags INT = NULL,
    @IN_login_id VARCHAR(150) = NULL,
    @IN_email VARCHAR(255) = NULL,
    @IN_password_crypt VARCHAR(65) = NULL


)
AS 
    BEGIN
        DECLARE @iNewestIdentity as INT;


        /* convert '' to null on char and varchar cols */
        SET @IN_login_id = CASE WHEN LTRIM(RTRIM(@IN_login_id)) = '' THEN NULL ELSE @IN_login_id END
        SET @IN_email = CASE WHEN LTRIM(RTRIM(@IN_email)) = '' THEN NULL ELSE @IN_email END
        SET @IN_password_crypt = CASE WHEN LTRIM(RTRIM(@IN_password_crypt)) = '' THEN NULL ELSE @IN_password_crypt END


        /* log the data */
        INSERT INTO MEMBERS
        (

            --ID,
            ORIG_ID, 
            SEQ, 
            SRC_MEMBER_ID, 
            FLAGS, 
            MEMBER_FLAGS, 
            ROLE_FLAGS, 
            VALIDATION_FLAGS, 
            LOGIN_ID, 
            EMAIL, 
            PASSWORD_CRYPT      
        ) 
        SELECT
            M.ORIG_ID, 
            M.SEQ + 1 SEQ, 
            M.SRC_MEMBER_ID, 
            ISNULL(@IN_flags, M.FLAGS) | 8 FLAGS, 
            ISNULL(@IN_member_flags, M.MEMBER_FLAGS) MEMBER_FLAGS, 
            ISNULL(@IN_role_flags, M.ROLE_FLAGS) ROLE_FLAGS, 
            ISNULL(@IN_validation_flags, M.VALIDATION_FLAGS) VALIDATION_FLAGS, 
            ISNULL(@IN_login_id, M.LOGIN_ID) LOGIN_ID, 
            ISNULL(@IN_email, M.EMAIL) EMAIL, 
            ISNULL(@IN_password_crypt, M.PASSWORD_CRYPT) PASSWORD_CRYPT
        FROM
            bfv_MEMBERS M
        WHERE
            M.FLAGS & 8 = 8 AND 
            M.ORIG_ID = @IN_orig_id
            --AND M.ID = @IN_id /* dont really need this right? e.g. can pass in orig_id and use that since it only looks for the current row */
        ;

        SET @iNewestIdentity = SCOPE_IDENTITY();


        /* set old row to inactive */
        UPDATE 
            MEMBERS
        SET 
            FLAGS = FLAGS &~ 8          
        WHERE
            ID = @IN_id /* need the id here as opposed to orig_id */
        ;


        RETURN


    END
有鉴于此,我如何处理应用程序需要更新当前有值的列,但需要将其设置为Null,同时仍然能够仅为需要更改的列传递参数的实例

出于上述原因,我不想在每次需要更新时都传递每个参数

这是我的。如您所见,当前,如果列的输入值为null,我们不会设置新值

CREATE PROCEDURE [dbo].[bfsp_update_MEMBER]
(   
    @IN_id INT = NULL,
    @IN_orig_id INT = NULL,

    @IN_flags INT = NULL,
    @IN_member_flags INT = NULL,
    @IN_role_flags INT = NULL,
    @IN_validation_flags INT = NULL,
    @IN_login_id VARCHAR(150) = NULL,
    @IN_email VARCHAR(255) = NULL,
    @IN_password_crypt VARCHAR(65) = NULL


)
AS 
    BEGIN
        DECLARE @iNewestIdentity as INT;


        /* convert '' to null on char and varchar cols */
        SET @IN_login_id = CASE WHEN LTRIM(RTRIM(@IN_login_id)) = '' THEN NULL ELSE @IN_login_id END
        SET @IN_email = CASE WHEN LTRIM(RTRIM(@IN_email)) = '' THEN NULL ELSE @IN_email END
        SET @IN_password_crypt = CASE WHEN LTRIM(RTRIM(@IN_password_crypt)) = '' THEN NULL ELSE @IN_password_crypt END


        /* log the data */
        INSERT INTO MEMBERS
        (

            --ID,
            ORIG_ID, 
            SEQ, 
            SRC_MEMBER_ID, 
            FLAGS, 
            MEMBER_FLAGS, 
            ROLE_FLAGS, 
            VALIDATION_FLAGS, 
            LOGIN_ID, 
            EMAIL, 
            PASSWORD_CRYPT      
        ) 
        SELECT
            M.ORIG_ID, 
            M.SEQ + 1 SEQ, 
            M.SRC_MEMBER_ID, 
            ISNULL(@IN_flags, M.FLAGS) | 8 FLAGS, 
            ISNULL(@IN_member_flags, M.MEMBER_FLAGS) MEMBER_FLAGS, 
            ISNULL(@IN_role_flags, M.ROLE_FLAGS) ROLE_FLAGS, 
            ISNULL(@IN_validation_flags, M.VALIDATION_FLAGS) VALIDATION_FLAGS, 
            ISNULL(@IN_login_id, M.LOGIN_ID) LOGIN_ID, 
            ISNULL(@IN_email, M.EMAIL) EMAIL, 
            ISNULL(@IN_password_crypt, M.PASSWORD_CRYPT) PASSWORD_CRYPT
        FROM
            bfv_MEMBERS M
        WHERE
            M.FLAGS & 8 = 8 AND 
            M.ORIG_ID = @IN_orig_id
            --AND M.ID = @IN_id /* dont really need this right? e.g. can pass in orig_id and use that since it only looks for the current row */
        ;

        SET @iNewestIdentity = SCOPE_IDENTITY();


        /* set old row to inactive */
        UPDATE 
            MEMBERS
        SET 
            FLAGS = FLAGS &~ 8          
        WHERE
            ID = @IN_id /* need the id here as opposed to orig_id */
        ;


        RETURN


    END

因此,您实际上是在尝试复制函数
UPDATE()
COLUMNS\u UPDATED()
提供的功能,对吗?不,该过程是从应用程序调用的。例如,一个成员表。用户可以更新他们的个人资料。假设用户想要删除他们的中间名。他们会这样做,然后按update。应用程序只检测到该字段已更改,因此它将调用存储过程,只传入该单个参数。所有其他参数都默认为NULL。但目前,上述过程忽略任何空参数。。。只允许从已更改的字段传入参数。如果表中有可为空的列,则尝试为传递到过程中的
NULL
值指定两种含义。第一个意思是:这个参数应该被忽略。第二种含义:将列的现有值设置为
NULL
。由于单个参数不能同时表达这两种含义,因此必须为每个可空列添加一个额外的显式参数,例如
@IgnoreParameterABC bit
@robarwebservices,如果您的表有100个可空列,那么您的过程将有200个参数。前100个参数包含每列的新值(可能
NULL
值)。这些参数默认为
NULL
。第二个100个参数只是
标志,指示过程是否应使用或忽略具有值的对应参数。
标志可以默认为“忽略”。调用这样的过程时,您必须显式地为正在更改的列及其标志设置参数。@Vladimir建议的一个变体是只引入一个附加参数来指定要更新的列。它可以是保存位图的varbinary(类似于COLUMNS_UPDATED),也可以是保存要更新的实际列名列表的varchar/nvarchar。