基于同一表中的值访问连接中的SQL Update一个表

时间:2013-02-13 20:40:29

标签: sql ms-access sql-update

我在Access中有一个名为“tempSpring_ASN”的表,其中包含以下字段(其中包括):

SHP_CUSTOM_5(自动编号)

RECORD_TYPE(文字)

PO_NUM(文字)。

我需要更改RECORD_TYPE的值,这样如果PO_NUM与前一条记录中的PO_NUM相同,则RECORD_TYPE应为“LIN”,否则(或者如果它是第一条记录),RECORD_TYPE应为“HDR”

我创建了以下查询以获取RECORD_TYPE的正确新值:

SELECT TOP 1 t1.SHP_CUSTOM_5,
    t1.PO_NUM AS CurrentValue,
    NULL AS PreviousValue,
    "HDR" AS RECORD_TYPE
FROM tempSpring_ASN AS t1
ORDER BY t1.SHP_CUSTOM_5
UNION ALL
SELECT t1.SHP_CUSTOM_5,
    t1.PO_NUM AS CurrentValue,
    t2.PO_NUM AS PreviousValue,
    IIf([CurrentValue]=[PreviousValue],'LIN','HDR') AS RECORD_TYPE
FROM tempSpring_ASN AS t1,
    tempSpring_ASN AS t2
WHERE t1.SHP_CUSTOM_5 = t2.SHP_CUSTOM_5 + 1
ORDER BY t1.SHP_CUSTOM_5;

我已将该查询保存为“tempSpring_ASN_With_PreviousRow”。现在我正在尝试使用它来使用以下查询更新原始tempSpring_ASN表:

UPDATE tempSpring_ASN INNER JOIN tempSpring_ASN_With_PreviousRow ON tempSpring_ASN.SHP_CUSTOM_5 = tempSpring_ASN_With_PreviousRow.SHP_CUSTOM_5 SET tempSpring_ASN.RECORD_TYPE = [tempSpring_ASN_With_PreviousRow].[RECORD_TYPE];

但我得到了,“操作必须使用可更新的查询。”我不确定是不是因为我正在尝试更新连接中的一个表,或者因为我试图根据同一个表中的值更新表,或者是由于其他原因。无论如何,我正在寻找有用的东西。

谢谢!

更新(无双关语)

我尝试过以下更新查询:

UPDATE tempSpring_ASN INNER JOIN Table5 ON tempSpring_ASN.SHP_CUSTOM_5 = Table5.SHP_CUSTOM_5 SET tempSpring_ASN.RECORD_TYPE = "zzz";

它工作正常。结果是tempSpring_ASN已更新,但Table5不是。显然,如果在SQL语句中连接了两个表,即使您在一个表上运行更新,它仍然不会尝试更新连接中的另一个表。既然如此,我不确定为什么我的原始更新查询不起作用。我知道tempSpring_ASN_With_PreviousRow不可更新,因为它是一个UNION查询,但我不是尝试来更新它。相反,我正在尝试更新tempSpring_ASN - 连接中的另一个表, 可更新。

更新2: 然后我尝试使用相关子查询,如下所示:

UPDATE tempSpring_ASN AS t
SET t.RECORD_TYPE = (
        SELECT RECORD_TYPE
        FROM (
            SELECT TOP 1 t1.SHP_CUSTOM_5,
                t1.PO_NUM AS CurrentValue,
                NULL AS PreviousValue,
                "HDR" AS RECORD_TYPE
            FROM tempSpring_ASN AS t1
            ORDER BY t1.SHP_CUSTOM_5
            UNION ALL
            SELECT t1.SHP_CUSTOM_5,
                t1.PO_NUM AS CurrentValue,
                t2.PO_NUM AS PreviousValue,
                IIf([CurrentValue] = [PreviousValue], 'LIN', 'HDR') AS RECORD_TYPE
            FROM tempSpring_ASN AS t1,
                tempSpring_ASN AS t2
            WHERE t1.SHP_CUSTOM_5 = t2.SHP_CUSTOM_5 + 1
            ORDER BY t1.SHP_CUSTOM_5
            )
        WHERE SHP_CUSTOM_5 = t.SHP_CUSTOM_5
        );

但我仍然得到“操作必须使用可更新的查询。”

更新3:

我认为错误是由于我正在使用联合查询。为了隔离这个问题,我尝试了以下内容(这不会给我我想要的结果,但会帮助我诊断问题。):

UPDATE tempSpring_ASN AS t
SET t.RECORD_TYPE = (
        SELECT TOP 1 RECORD_TYPE
        FROM tempSpring_ASN_With_PreviousRow
        );

它给了我同样的错误。所以问题现在变成了,为什么我不能使用联合查询的输出的单个值来设置记录集中的值?

1 个答案:

答案 0 :(得分:1)

我也在你的新问题中发布了这个答案。

嗨AYS,

在Access中,需要在表上运行Update查询。 由于UNION查询是多组记录的组合,因此结果集不再是表,并且不能成为Update查询的对象,因为结果集中的记录不再与任何一个特定表唯一标识(甚至如果他们理论上可能是)。 Access是硬编码的,可以将每个UNION查询视为只读,这在有多个基础表时是有意义的。还有许多其他条件(例如SELECT语句中的子查询)也会触发此条件。

以这种方式思考:如果你没有使用TOP 1并且你的UNION查询返回了多个结果,那么JET如何知道将哪个结果应用于表中的唯一记录?因此,JET将所有此类案件视为相同。

不幸的是,即使所有数据都来自同一个表,也是如此。在这种情况下,JET优化器可能根本不够智能,无法实现这种情况,并以不使用UNION的方式重新查询查询。

在这种情况下,您仍然可以通过重新查询查询来获得所需内容,以便所有内容都引用您的基表。例如,您可以使用以下作为SELECT查询来获取先前SHP_CUSTOM_5记录的PO_NUM值:

SELECT
t1.SHP_CUSTOM_5
, t1.PO_NUM
, t1.SHP_CUSTOM_5 -1 AS PREV_RECORD

, (SELECT
t2.PO_NUM
FROM
tempSpring_ASN As t2
WHERE
t2.SHP_CUSTOM_5 = (t1.SHP_CUSTOM_5 -1)
) AS PREV_PO

FROM
tempSpring_ASN AS t1
;

然后,您可以将此短语作为更新查询,如下所示,以执行“LIN”更新:

UPDATE
tempSpring_ASN AS t1 

SET 
t1.RECORD_TYPE = "LIN"

WHERE
t1.PO_NUM=

(
SELECT 
t2.PO_NUM

FROM
tempSpring_ASN As t2

WHERE
t2.SHP_CUSTOM_5 = (t1.SHP_CUSTOM_5 -1)
)
;

此代码在我使用虚拟数据运行的测试中取得了成功。

关于“HDR”更新,您实际上正在执行两项单独的更新。 1)如果PO_NUM与先前记录的PO_NUM匹配,则将RECORD_TYPE设置为“LIN” 2)如果是第一条记录,请将RECORD_TYPE设置为“HDR”

我不清楚为什么在一个查询中执行这些操作会有好处。我建议使用您在原始SELECT查询示例中使用的SHP_CUSTOM_5方法使用“TOP 1”执行HDR更新,因为这将是一个相对简单的UPDATE查询。可以在更新查询中使用IIF(),但我不知道您将从所需的额外时间和复杂性中获得哪些额外好处(它很可能只是更不易读)。

祝你好运!