1

我在 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
        );

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

4

1 回答 1

1

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

嗨,AYS,

在 Access 中,需要对表运行更新查询。由于 UNION 查询是多组记录的组合,结果集不再是一个表,也不能成为 Update 查询的对象,因为结果集中的记录不再与任何一个特定表唯一标识(甚至如果理论上可以的话)。访问被硬编码以将每个 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 查询。可以在 Update 查询中使用 IIF(),但我不知道您会从所需的额外时间和复杂性中获得什么额外好处(它很可能只是可读性低得多)。

祝你好运!

于 2013-02-14T23:50:35.623 回答