2017-04-15 108 views
2

我需要插入訪問數據庫。但是如果列dup已經在表格中,則跳過該行。ms access access insert into no duplicates

我到目前爲止是這樣的:

<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主鍵。然後它將INSERT重複。如果我讓一個主鍵。然後我得到一個錯誤。

我想我需要類似MySQL的東西。在DUPLICATE KEY UPDATE上。

或者可能像在Oracle中一樣處理dup_val_on_index異常。

@Gord湯普森

我試過(不知道我這樣做是正確):

<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> 

,但我得到[微軟] [ODBC Microsoft Access驅動程序] COUNT字段不正確。

什麼是?在你的選擇聲明?

+0

如果這是VBA,可以用'Set Warnings False'關閉警告,運行SQL,然後'Set Warnings True'或使用CurrentDb.Execute。回顧http://stackoverflow.com/questions/14383503/on-duplicate-key-update-same-as-insert – June7

+0

[重複密鑰更新與插入相同]的可能重複(http://stackoverflow.com/questions/ 14383503/on-duplicate-key-update-same-as-insert) – June7

+0

「小時」查詢中數據的來源是什麼?如果它來自同一個數據庫中的一個表,那麼跳過cfloop並使用一個'insert into/select ... from ...'語句包含一個'where not exists ...'語句會更有效率。 – Leigh

回答

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提供商無法工作。

+0

出於好奇,爲什麼它不適用於OLEDB? – Leigh

+0

@Leigh - 我不知道,這只是Access ODBC驅動程序和Access OLEDB提供程序之間的細微差別之一。 –

+0

很高興知道。自從我使用OLEDB以來已經有一段時間了。從來沒有真正掌握所有的差異,除了知道有一些:) – Leigh

3

更新:

如果由於某種原因,你不能直接查詢外部數據庫,嘗試使用上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,ecetera)。例如:

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

因此,如果數據是從一個(支持)外部數據庫或在同一個數據庫內的另一個表,它是一個LOT更有效地跳過cfloop和運行單個 INSERT INTO/SELECT查詢。只需將它與OUTER JOIN或NOT EXISTS子句結合,即可排除目標表中已存在的記錄。

免責聲明 - 我沒有用在很長一段時間的訪問,但語法應該是這樣的:

選項#1 - OUTER JOIN

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 - NOT EXISTS

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 
     ) 
+0

這將工作,如果小時在另一個數據庫? – Thomas

+0

(編輯)從理論上講,但是..我沒有再安裝Access,所以我無法驗證它。試一試。現在跳過INSERT部分,看看是否有任何一條SELECT語句有效。 – Leigh

+0

順便說一句,這個概念是完美的,這肯定會與同一個數據庫中的表一起工作。但是,從我記得MS Access對交叉數據庫查詢有一些限制,所以有可能這不被支持。 – Leigh

0

我想發佈我最終做的事以防萬一它幫助某人。

感謝@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中。

+0

感謝您發佈您的最終代碼。雖然它們看起來很相似,但QoQ的方法使用CF內存,而不是將工作轉移到數據庫(通常更適合工作)。另外,請記住'where in(....)'子句往往會減慢列表中更多的項目。因此,您可能仍然希望調查「鏈接查詢」和/或「外部數據庫」選項以查看它是否更有效。特別是如果最終的'insert'查詢涉及一個循環來一次添加一條記錄。雖然有時不可避免,循環往往是插入數據最慢的方法... – Leigh