【问题标题】:ms access insert into no duplicatesms访问插入不重复
【发布时间】:2017-09-11 18:55:18
【问题描述】:

我需要插入一个访问数据库。但如果 dup 列已经在表中,则跳过该行。

到目前为止,我所拥有的是:

<cfoutput  query="hours">
<cfquery name="Employee" datasource="test">

INSERT INTO Tbl_Hours_Comments
(ID, ship_num, dup)
    values(#hours.id#, #hours.ship#, #hours.dup#)
</cfquery>
</cfoutput>

如果我不将 dup 设为主键。然后它将插入重复项。如果我制作主键。然后我得到一个错误。

我想我需要类似 MySQL 的东西。重复密钥更新。

或者可能像 Oracle 中的 dup_val_on_index 异常处理。

@戈德汤普森

我试过了(不确定我是否做得对):

<cfoutput  query="hours">
<cfquery name="Insert_Employee" datasource="trung">
INSERT Tbl_Hours_Comments (ID, ship_num, dup)

values(#hours.id#, #hours.ship#, #hours.dup#)
SELECT ? as dup
  FROM( SELECT COUNT(*) as n from Tbl_Hours_Comments) as Dual



WHERE NOT EXISTS
        (   SELECT *
            FROM Tbl_Hours_Comments
            WHERE dup = ?
        )


</cfquery>
</cfoutput>

但我得到 [Microsoft][ODBC Microsoft Access Driver]COUNT 字段不正确。

什么是?在您的选择声明中?

【问题讨论】:

  • 如果这是 VBA,可以使用 Set Warnings False 关闭警告,然后运行 ​​SQL 然后 Set Warnings True 或使用 CurrentDb.Execute。评论stackoverflow.com/questions/14383503/…
  • “小时”查询中的数据来源是什么?如果它来自同一数据库中的表,则跳过 cfloop 并使用包含 where not exists... 子句的单个 insert into / select ... from ... 语句会更有效。
  • hours 来自一个查询的 cf 查询。数据位于另一个数据源中。
  • 澄清一下,您是指同一个 MS Access 数据库中的另一个 吗?还是一个完全独立的数据库?如果是这样,哪种类型 - MS Access、SQL Server 等等? MS Access 支持querying external databases

标签: sql ms-access coldfusion


【解决方案1】:

我想发布我最终所做的事情,以防它对某人有所帮助。

感谢@Leigh 和@Gord 在这个问题上的帮助。

这就是我最终解决它的方法。这与 Leigh 和 Gord 的子查询方式非常相似。

我 CFQUERY 两个表(QueryA 和 QueryB)。

然后我用了这个(来自https://coldfusionblog.wordpress.com/2012/01/11/how-to-do-an-outer-join-in-query-of-queries/):

<cfquery name="unique">
SELECT *
FROM QueryA
WHERE QueryA.ID NOT IN (#ValueList(QueryB.ID)#)
</cfquery>

获取 QueryA 中不在 QueryB 中的元素列表。

然后我使用另一个插入查询将所有新的唯一元素插入到 QueryB 中。

【讨论】:

  • 感谢您发布最终代码。尽管它们看起来相似,但 QoQ 的方法使用 CF 内存,而不是将工作卸载到数据库(通常更适合该工作)。另外,请记住where not in (....) 子句往往会减慢列表中的项目越多。因此,您可能仍想调查“链接查询”和/或“外部数据库”选项,看看它是否更有效。特别是如果最终的insert 查询涉及一次添加一条记录的循环。虽然有时不可避免,但循环往往是插入数据最慢的方法......
【解决方案2】:

更新:

如果由于某种原因您无法直接查询外部数据库,请尝试使用Gord Thompson's suggestion 的变体。它不如 INSERT /SELECT .. FROM Table 高效,但是 ... 将与 MS Access 一起使用。

INSERT INTO Tbl_Hours_Comments (ID, ship_num, dup)
SELECT <cfqueryparam value="#hours.id#" cfsqltype="(your column type here)">
       , <cfqueryparam value="#hours.ship#" cfsqltype="(your column type here)">
       , <cfqueryparam value="#hours.dup#" cfsqltype="(your column type here)">
WHERE  NOT EXISTS
       (
          SELECT NULL
          FROM   Tbl_Hours_Comments dupe
          WHERE  dupe.id = <cfqueryparam value="#hours.id#" cfsqltype="(your column type here)">
          AND    dupe.ship = <cfqueryparam value="#hours.ship#" cfsqltype="(your column type here)">
          AND    dupe.dup = <cfqueryparam value="#hours.dup#" cfsqltype="(your column type here)">
       )

“小时”查询中的数据来源是什么? MS Access 支持直接使用 IN 子句查询某些 external databases(MS Access、SQL Server、Excel 等)。示例:

 SELECT Column1, Column2
 FROM   TableName IN 'c:\path\to\external.mdb'

因此,如果数据来自(支持的)外部数据库或同一数据库中的另一个表,跳过cfloop 并运行 single INSERT INTO / SELECT 会更有效询问。只需将其与 OUTER JOIN 或 NOT EXISTS 子句结合使用,即可排除目标表中已存在的记录。

免责声明 - 我很久没有使用 Access,但语法应该是这样的:

选项 #1 - 外部联接

INSERT INTO Tbl_Hours_Comments (ID, ship_num, dup)
SELECT ex.id, ex.ship, ex.dup
FROM   OtherTable ex LEFT JOIN Tbl_Hours_Comments dupe
          ON dupe.id = ex.id
          AND dupe.ship = ex.ship
          AND dupe.dup = ex.dup
WHERE  dupe.id IS NULL

选项 #2 - 不存在

INSERT INTO Tbl_Hours_Comments (ID, ship_num, dup)
SELECT ex.id, ex.ship, ex.dup
FROM   OtherTable ex
WHERE  NOT EXISTS
       (
          SELECT NULL
          FROM   Tbl_Hours_Comments dupe
          WHERE  dupe.id = ex.id
          AND    dupe.ship = ex.ship
          AND    dupe.dup = ex.dup
       )

【讨论】:

  • (编辑)理论上,但是..我没有再安装 Access,所以我无法验证它。试一试。暂时跳过 INSERT 部分,看看其中一个 SELECT 语句是否有效。
  • 顺便说一句,这个概念是合理的,这肯定适用于同一数据库中的表。但是,据我所知,MS Access 在跨数据库查询方面有一些限制,因此可能不支持。
  • “MS Access 在跨数据库查询方面有一些限制” - 确实如此,但如果 Access 数据库包含指向外部表的 ODBC 链接表,那么它的行为非常很像本地餐桌。 (“某些条件适用。您的里程可能会有所不同。等等。”:)
  • @GordThompson - 哦……忘了这些。所以“理论上”他们可以链接到远程表并且 INSERT / SELECT 应该工作。酷。
【解决方案3】:

如果您使用 Microsoft Access ODBC 驱动程序更新数据库,那么您可以使用INSERT ... SELECT ... WHERE NOT EXISTS。以下示例是在 Python 中编写的,但看起来您应该能够在 ColdFusion 中执行类似的操作。

import pyodbc
cnxn = pyodbc.connect("DSN=db1")  # Microsoft Access ODBC
crsr = cnxn.cursor()

hours_ship = "ship102"  # test data
hours_dup = 3           #

sql = """\
INSERT INTO Tbl_Hours_Comments (ship_num, dup)
SELECT ? as ship_num, ? AS dup
FROM (SELECT COUNT(*) AS n FROM Tbl_Hours_Comments) AS Dual
WHERE NOT EXISTS (SELECT * FROM Tbl_Hours_Comments WHERE dup = ?)
"""
params = (hours_ship, hours_dup, hours_dup)
crsr.execute(sql, params)
cnxn.commit()
print("{} row(s) inserted".format(crsr.rowcount))
crsr.close()
cnxn.close()

请注意,此方法无法使用 Microsoft Access OLEDB 提供程序。

【讨论】:

  • 只是出于好奇,为什么它不能与 OLEDB 一起使用?
  • @Leigh - 我不确定,这只是 Access ODBC 驱动程序和 Access OLEDB 提供程序之间的细微差别之一。
  • 很高兴知道。自从我使用 OLEDB 以来已经有一段时间了。从来没有真正了解所有差异,除了知道有一些:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
相关资源
最近更新 更多