使用coldfusion动态更新显示顺序

Dynamically update display order using coldfusion

我是一名自学成才的编程爱好者,为当地一家小型非营利组织提供志愿服务,我正在使用 coldfusion 更新其网站管理部分。

其中一部分用于在前端按分配的顺序显示志愿者。我在 table 中添加了一个“显示”列,我在其中设置了如何显示志愿者的顺序号。 (1 第一,2 第二,依此类推)

我希望能够在更新或添加记录时动态重新排列显示顺序。通常我会请一位高级程序员来做这件事,但这不在预算之内,所以我想我会试一试。

示例:

1 = 1

2 = 2

3 = 3

目前,如果我将 3 更改为 1,我会得到两个 1,而 3 会消失。 (预期)

1 = 1(以前是 3)

1 = 1

2 = 2

我希望更新将其下方的所有记录也移动到更新。

(如果我把3移到1)

1 = 1(以前是 3)

2 = 2(曾经是 1)

3 = 3(以前是 2)

(如果我把3移到2)

1 = 1

2 = 2(以前是 3)

3 = 3(以前是 2)

目前我只是单独更新每条记录,但这显然不理想,尤其是当志愿者名单增长到十几岁或更多时。

我花了好几个小时寻找有关如何执行此操作的指导,但不知道从哪里开始。任何帮助将不胜感激。

更新表单代码如下:

            <div class="form-group">
                <label for="Display">Display Order</label>
                <select name="display" class="form-control form-control-lg" required>
                    <option value="">Select Display Order</option>
                    <cfoutput query="GetBioDisplay"><option value="#GetBioDisplay.display#">#GetBioDisplay.display#</option></cfoutput>
                </select>
            </div>

这是更新查询:

            <cfquery name = "UpdateProfile" datasource="#dsn#">
                UPDATE DBO.PROFILE
                    SET firstname  =  '#form.firstname#', 
                    lastname       =  '#form.lastname#', 
                    title          =  '#form.title#',
                    email          =  '#form.email#',
                    display        =  '#form.display#', 
                    Picture        =  '#form.picture#',
                    profile        = '#form.profile#',
                    credentials    = '#form.credentials#' 
                    WHERE ID       =   #url.id#
            </cfquery>

这是我用于用户/前端的查询:

            <cfquery name="GetProfile" datasource="#request.dsn#">
                SELECT ID, FIRSTNAME, LASTNAME, TITLE, EMAIL, 
                    PICTURE, DISPLAY, PROFILE, CREDENTIALS
                        FROM DBO.PROFILE
                            ORDER BY DISPLAY
            </cfquery>

添加第二个更新查询

update dbo.profile
set display = display + 1
where display >= <cfqueryparam CFSQLType = "cf_sql_integer" value = "#form.display#">
and id <> <cfqueryparam CFSQLType = "cf_sql_integer" value = "#url.id#">

您也应该在其他查询中使用查询参数。您当前更新查询的编写方式,会在 O'Malley 等名称上引发错误。

编辑从这里开始 为了让用户看到他们应该看到的,改变这个

     <cfoutput query="GetBioDisplay">
     <option value="#GetBioDisplay.display#">#GetBioDisplay.display#
     </option>
     </cfoutput>

至此

     <cfoutput query="GetBioDisplay">
     <option value="#GetBioDisplay.display#">#GetBioDisplay.rownumber#
     </option>
     </cfoutput>

这将显示用户编号,例如 1、2、3 等

您可以在 WHERE 子句中使用 CASE/WHEN 条件语句来更新为正确的值,无论您移动记录的方向如何。您只需要传递两个值:您要更新的位置 (url.id) 和您要更新到的位置 (form.position).

SQL Fiddle MS SQL Server 2017 架构设置:

CREATE TABLE test(
    display int NOT NULL,
    item varchar(2000) NULL
) ;

INSERT INTO test (display, item)
VALUES 
    (1,'a')
  , (2,'b')
  , (3,'c')
  , (4,'d')
  , (5,'e')
  , (6,'f')
  , (7,'g')
  , (8,'h')
  , (9,'i')
  , (10,'j')
;

查询 - 向上排序:

/* Move 8 to 4 - UP */

DECLARE @updDisp int = 8
DECLARE @updTo int = 4

UPDATE test
SET display = (CASE 
    WHEN display = @updDisp THEN @updTo 
    WHEN @updDisp < @updTo THEN display-1
    WHEN @updDisp > @updTo THEN display+1
    END
)
WHERE 
    ( display BETWEEN @updDisp AND @updTo )
    OR 
    ( display BETWEEN @updTo AND @updDisp )
;

结果

SELECT * FROM test ORDER BY display 


| display | item |
|---------|------|
|       1 |    a |
|       2 |    b |
|       3 |    c |
|       4 |    h |
|       5 |    d |
|       6 |    e |
|       7 |    f |
|       8 |    g |
|       9 |    i |
|      10 |    j |

查询 - 下单:

/* Move 4 to 8 - DOWN */

DECLARE @updDisp int = 4
DECLARE @updTo int = 8

UPDATE test
SET display = (CASE 
    WHEN display = @updDisp THEN @updTo 
    WHEN @updDisp < @updTo THEN display-1
    WHEN @updDisp > @updTo THEN display+1
    END
)
WHERE 
    ( display BETWEEN @updDisp AND @updTo )
    OR 
    ( display BETWEEN @updTo AND @updDisp )

结果

SELECT * FROM test ORDER BY display 


| display | item |
|---------|------|
|       1 |    a |
|       2 |    b |
|       3 |    c |
|       4 |    d |
|       5 |    e |
|       6 |    f |
|       7 |    g |
|       8 |    h |
|       9 |    i |
|      10 |    j |

因此您的 CF 代码将如下所示:

//// process and validate form variables here ////
local.updDisp = url.id
local.updTo   = form.display
//////////////////////////////////////////////////

<cfquery name="UpdateProfile" datasource="#dsn#">
    UPDATE DBO.PROFILE
    SET display = (
        CASE 
            WHEN display = #val(local.updDisp)# THEN <cfqueryparam cfsqltype="cf_sql_integer" value="#local.updTo#">
            WHEN #val(local.updDisp)# < #val(local.updTo)# THEN display-1
            WHEN #val(local.updDisp)# > #val(local.updTo)# THEN display+1
        END
    )
    WHERE ( display BETWEEN <cfqueryparam cfsqltype="cf_sql_integer" value="#local.updDisp#"> AND <cfqueryparam cfsqltype="cf_sql_integer" value="#local.updTo#"> )
        OR 
        ( display BETWEEN <cfqueryparam cfsqltype="cf_sql_integer" value="#local.updTo#"> AND <cfqueryparam cfsqltype="cf_sql_integer" value="#local.updDisp#"> )
</cfquery>

我不确定您是否可以在 SET 内的 CASE 语句中使用 cfqueryparam,而且我没有办法测试。无论如何,既然我们知道我们应该始终使用 integers,那么 val() 函数应该提供与 cfqueryparam 在这种情况下所做的相同的保护。

在用户输入方面,我的心态也比较偏执。 cfqueryparam 非常擅长它的工作,但它并不能防止所有问题。我仍然建议您在允许这些值出现在数据库附近的任何位置之前进行某种预处理。