MS Access中的SQL更新困难 - 操作必须使用可更新的查询

时间:2009-02-11 14:55:00

标签: sql ms-access sql-update

我有一个select查询,它执行一些文本操作以基本上重新格式化字段,以便我可以在另一个表中查找它:

如果我的第一个表格中有一个像“J1 / 2”这样的字段,它会在相应字段中的J1和J2的不同表中查找记录的ID。

这一切都运作良好。

现在我想更新原始表,因此我不必再使用此字符串操作进行查找,但我在更新查询中的尝试以“操作必须使用可更新查询”结束

有什么想法吗?

我的SELECT语句:

SELECT DISTINCT
t1.DD,
t1.TN,
t1.DD & " J" & MID(t1.TN,2,1) AS CalculatedStart,
t1.DD & " J" & MID(t1.TN,4,1) AS CalculatedEnd,
t2.ID
FROM t1 INNER JOIN t2
ON (t1.DD & " J" & MID(t1.TN,2,1)=t2.StartLink)
AND (t1.DD & " J" & MID(t1.TN,4,1)=t2.EndLink)
WHERE t1.TN Like "J?/?"
AND t1.DD Like "M*";

召回 - 这很好用,我从另一端得到了必要的t2.ID。

所以我想做点什么:

UPDATE t1 SET t2ID = (
    SELECT Query1.ID
    FROM Query1
    WHERE t1.DD=Query1.DD
    AND t1.TN=Query1.TN
    )
WHERE t1.TN Like "J?/?"
AND t1.DD Like "M*";

只有这个失败了。这是在MS Access本身,所以我无法想象像大多数“操作必须使用可更新的查询”问题的实际权限问题似乎是。

编辑:试图简化不起作用的案例。

此UPDATE查询很好:

UPDATE t1
SET t2ID="Unknown"
WHERE TN LIKE "J?/?"
AND DD LIKE "M*";

这个失败了(感谢Goedke - 这个例子显然失败了,因为子查询返回的结果超过了1个。我过于简单了,试图找到我的问题)

UPDATE t1
SET t2ID=(SELECT ID FROM t2)
WHERE TN LIKE "J?/?"
AND DD LIKE "M*";

那么我的子查询语法在某种程度上是错误的吗?

编辑:这个SELECT语句也没关系:

SELECT t1.OA, t1.DD, t1.TN, t1.HATRIS,
    query1.DD, query1.TN, query1.ID
FROM t1 INNER JOIN query1
ON t1.DD=query1.DD
AND t1.TN=query1.TN

此外,在上面的select语句中使用count表示每个(DD,TN)组合正好返回1个ID

编辑:

我现在最简单的情况 - 使用各种SELECT语句我现在有一个只有2列的表 - t1的主键和我想插入t1的值。

我似乎仍然无法写

UPDATE t1 SET t1.f2 = (SELECT t2.f2 FROM t2 WHERE t2.f1 = t1.f1)

其中t1的主键是f1。即使添加WHERE t1.f1 IN(SELECT f1 FROM t2)也无济于事。 (添加以消除子查询返回0结果的可能性)

7 个答案:

答案 0 :(得分:17)

我必须权衡David W. Fenton对OP的评论。

这是Jet / ACE非常烦人的问题。但请尝试:

  1. 转到查询属性(单击 窗格的背景 表格显示)和设置 “独特记录”为“是”
  2. 选项1相当于添加 有点奇怪的样子 DISTINCTROW关键字 SELECT条款,例如
  3. UPDATE DISTINCTROW tblClient 
           INNER JOIN qryICMSClientCMFinite 
              ON tblClient.ClientID = qryICMSClientCMFinite.ClientID
       SET tblClient.ClientCMType = "F";
    

    这解决了涉及此错误消息的许多问题,这几乎是荒谬的。

    简而言之,这就是MS Access - 如果您不知道问题x的商业秘密解决方法,您可能需要数天时间才能找到答案。要知道10,000个解决方法是对Access进行编程。这对于没有经验的人来说是否足够警告?

答案 1 :(得分:7)

这对我有用(Access 2000)

UPDATE DISTINCTROW T1 inner join T2 on T2.f1 = T1.f1  SET f2 = f2;

答案 2 :(得分:6)

除非t2中只有一条记录,否则(SELECT ID FROM t2)的子查询无法工作。您希望使用哪个ID?

正在报告的错误消息通常在您有联接时发生,并且不包括更新回数据绑定表单中的表所需的所有主键(例如,您的原始DISTINCT会破坏有关键的信息,因此,如果它被绑定到一个表单,表单将无法保存。)

您正在使用DISTINCT的事实会让我怀疑子查询在更复杂的示例中返回多行。这可能是分配子查询结果时最常见的问题:对where子句进行约束。

我在分配子查询时遇到的另一个问题是内部查询的语法是否不正确。至少对于SQL 2000和2005后端,查询处理器将静默失败并在这种情况下返回NULL。 (据我所知,这是一个错误:我认为没有理由为什么会在子查询中默默地允许在顶层返回错误的东西......但它确实存在。)

编辑: 为了确保保罗和我都没有发疯,我创建了以下表格:

t1 | ID, FK, Data
t2 | ID2, Data2

我做了除了ID和ID2上的主键之外还放置了任何约束。所有字段都是文本,这与我通常用于ID的字段不同,但应该是无关紧要的。

T1:

ID  FK  Data
Key1        Data1
Key2        Data2
Key3        Data3

T2:

ID2 Data2
Key1    DataA
Key2    DataB
Key3    DataC

表格的查询:

UPDATE t1 SET t1.FK = (select ID2 from t2 where t2.ID2 = t1.ID);

保罗得到的信息失败了。

select *, (select ID2 from t2 where t2.ID2 = t1.ID) as foreign from t1, 

按预期工作,因此我们知道子查询语法不应该受到责备。

UPDATE t1 SET t1.FK = 'Key1'

也按预期工作,因此我们没有损坏或不可更新的目的地。

注意:如果我将数据库后端从本机更改为SQL 2005,则更新有效!有点谷歌搜索,我发现Access MVP建议DLOOKUP替换子查询:

http://www.eggheadcafe.com/software/aspnet/31849054/update-with-subquerycomp.aspx

显然这是Access SQL中的一个错误,在使用SQL Express 2000或更高版本的后端时可以避免这个错误。 (“访问更新子查询”的谷歌搜索结果支持这一理论)。

请点击此处了解如何使用此解决方法:http://www.techonthenet.com/access/functions/domain/dlookup.php

答案 3 :(得分:6)

我没有阅读整个帖子,但这是我正在使用的解决方案:

update (select * from t1 inner join t2 on t1.key = t2.key) set t1.field1 = t2.field2

并且在我的MS Access中工作正常。

答案 4 :(得分:1)

我的解决方案是以这种方式改变我的SQL。

  update (select o.pricein, g.pricein from operations o left join goods g on g.id = o.goodid where o.opertype = 4 and o.acct = 1) 
  set o.pricein = g.pricein

答案 5 :(得分:1)

我使用Access 2010遇到了同样的错误("操作必须使用可更新的查询")我正在使用内部联接执行简单的更新查询。我所做的只是在我加入的表格中添加一个主键(当然,在我正在更新的表格中已有一个),一切正常。

答案 6 :(得分:0)

对于这一个:UPDATE t1 SET t1.f2 =(SELECT t2.f2 FROM t2 WHERE t2.f1 = t1.f1)

UPDATE t1 INNER JOIN t2 ON t1.f1 = t2.f1 SET t1.f2 = [t2].[f2];