2014-01-28 2 views
1

나는 제어 할 수없는 ODBC 서버에 대한 MS Access를 사용하여 통과 쿼리에 대한 업데이트를 만들려고합니다. 내가 패스 쓰루를 사용해야하는 이유는 내가 접근하는 레코드가 255 개 이상의 필드를 가지고 있기 때문입니다 (가능한 경우 연결된 테이블을 사용합니다). 나는이 자원을 사용하고MS 액세스 통과 쿼리 업데이트

패스 스루를 사용하여 데이터를 얻기 위해 (http://www.techonthenet.com/access/tutorials/passthrough/basics09.php)

쿼리는 단순히 : SELECT FullName, PointNumber FROM DNP3.CDNP3AnalogIn

는 ODBC 연결 str을이다 : Access 데이터베이스 내부 지금 ODBC;DSN=SCX6_DB;LOCATION=Main;UID=admin;PWD=password;LOCALTIME=False;

필드 (FullName, PointNumber)에 대해 동일한 이름의 테이블 (SCADA DB 태그)이 있고 Update Passthrough 쿼리를 사용하여 ODBC 데이터베이스 내의 필드를 업데이트하려고하지만이 작업을 수행하는 방법이 확실하지 않습니다.

내가 DNP3_CDNP3AnalogIn 쿼리로 이전 쿼리를 저장하고 새 쿼리 만들려고 :

UPDATE [DNP3_CDNP3AnalogIn Query] INNER JOIN [SCADA DB Tags] ON 
[DNP3_CDNP3AnalogInQuery].FullName = [SCADA DB Tags].FullName 
SET [DNP3_CDNP3AnalogIn Query].[PointNumber] = [SCADA DB Tags].[PointNumber]; 

을하지만 Access에서 오류가 발생합니다 : Operation must use an updateable query.

내가이 일을 어떻게든지이 알고 있지만 예를 찾을 수없는 것 같습니다 (정확한 문구를 검색하지 못할 수도 있음). Microsoft 페이지 (http://technet.microsoft.com/en-us/library/bb188204%28v=sql.90%29.aspx)는 말합니다 : There is, however, one important limitation: the results returned by SQL pass-through queries are always read-only. If you want to enable users to perform updates based on the data retrieved, you must write code to handle this. 불행히도 그것을 수행하는 예제를 제공하지 않습니다!

아무에게도 해결책을 줄 수 있습니까? 필요한 경우 VBA를 사용할 수 있습니까? 필요하다면 더 많은 배경을 줄 수도 있습니다. 불행히도 저는 Access의 전문가는 아닙니다. 저는 저에게 시간을 절약 할 수있는 자동화 된 솔루션을 제안하려고합니다.

답변

2

그들은 아마 이런 식으로 뭔가 의미 "당신이, 당신이 처리하는 코드를 작성해야합니다 [통과 쿼리에서] 검색 한 데이터를 기반으로 업데이트를 수행 할 수 있도록하려면"고 말했다

Option Compare Database 
Option Explicit 

Public Sub UpdateSqlServer() 
    Dim cdb As DAO.Database, rst As DAO.Recordset 
    Dim con As Object ' ADODB.Connection 
    Dim cmd As Object ' ADODB.Command 
    Const adParamInput = 1 
    Const adInteger = 3 
    Const adVarWChar = 202 

    Set cdb = CurrentDb 
    Set rst = cdb.OpenRecordset(_ 
      "SELECT " & _ 
       "[SCADA DB Tags].FullName, " & _ 
       "[SCADA DB Tags].PointNumber " & _ 
      "FROM " & _ 
       "[DNP3_CDNP3AnalogIn Query] " & _ 
       "INNER JOIN " & _ 
       "[SCADA DB Tags] " & _ 
        "ON [DNP3_CDNP3AnalogIn Query].FullName = [SCADA DB Tags].FullName", _ 
      dbOpenSnapshot) 

    Set con = CreateObject("ADODB.Connection") 
    con.Open "DSN=SCX6_DB;" 
    Set cmd = CreateObject("ADODB.Command") 
    cmd.ActiveConnection = con 
    cmd.CommandText = _ 
      "UPDATE DNP3.CDNP3AnalogIn SET " & _ 
       "PointNumber=? " & _ 
      "WHERE FullName=?" 
    cmd.Parameters.Append cmd.CreateParameter("?", adInteger, adParamInput) ' PointNumber 
    cmd.Parameters.Append cmd.CreateParameter("?", adVarWChar, adParamInput, 255) ' FullName 
    cmd.Prepared = True 

    Do Until rst.EOF 
     cmd.Parameters(0).Value = rst!PointNumber 
     cmd.Parameters(1).Value = rst!FullName 
     cmd.Execute 
     rst.MoveNext 
    Loop 
    Set cmd = Nothing 
    con.Close 
    Set con = Nothing 
    rst.Close 
    Set rst = Nothing 
    Set cdb = Nothing 
End Sub 

주 :

  1. 코드는 기존의 ODBC의 DNS를 사용합니다.
  2. SQL 문은 업데이트를 수행하고 효율성을 높이고 SQL 인젝션과 관련된 오류를 방지하기 위해 준비된 문을 사용합니다.
  3. 원본 Recordset은 통과 쿼리에서 INNER JOIN을 수행하여 코드가 서버에서 실제로 이있는 행만 업데이트하려고 시도하는지 확인합니다. 서버에 있습니다.
+0

감사합니다. cmd.Execute (Microsoft ODBC 드라이버 관리자 : SQL 데이터 형식이 범위를 벗어났습니다.)에서 오류가 발생합니다.나는 이것이 PointNumber에 대해 잘못된 유형을 보내는 것으로 생각합니다. 데이터베이스 스키마에서 : PointNumber는 Word (Unsigned)입니다. 나는 당신이 넣은 것처럼 Integer 대신에이 캐스팅을 만드는 법을 정말로 모르겠습니다. – reubenb87

+0

실제로 'FullName'필드는 '.'문자가있는 문자열이므로 문제가 있습니다. 및 '문자. "FullName = 'This is a test fullname'"과 같이 FullName 예제로 업데이트 쿼리를 하드 코딩하면됩니다. 하지만 캡슐에 넣으면? 처럼 '?' ("WHERE FullName = '?'") 작동하지 않습니다. 어떤 힌트? – reubenb87

+0

FullName 필드에서 adVarWChar 대신 adVarChar를 사용하여 문제가 해결되었습니다. 무리 감사! 난 단지 오류를 디버그하기 쉬운 곳으로 돌려주기를 바란다. – reubenb87

1

[DNP3_CDNP3AnalogIn Query]가 서버 측이고 [SCADA DB Tags] 테이블이 로컬 기반이라고 말하는가? 이 경우 통과 쿼리를 사용할 수 없습니다.

그러나 테이블이 다른 위치에 있기 때문에 패스가 동시에 양쪽을 만질 수는 없습니다.

하지만 루프에서 "단일"서버 측 (패스 - 스루)을 실행할 수 있습니다. 통과 쿼리를 설정하고 저장하면이 코드가 작동합니다.

Dim qdfPass  As DAO.QueryDef 

    Dim rstLocal  As DAO.Recordset 
    Dim strSQL  As String 
    Dim strSQL2  As String 

    Set qdfPass = CurrentDb.QueryDefs("MyPass") 

    strSQL = "UPDATE [DNP3_CDNP3AnalogIn Query] " & _ 
      "SET [DNP3_CDNP3AnalogIn Query].[PointNumber] = 'xxxx' " & _ 
      "WHERE [DNP3_CDNP3AnalogInQuery].FullName = 'zzzz' " 

    Set rstLocal = CurrentDb.OpenRecordset("[SCADA DB Tags]") 

    Do While rstLocal.EOF = False 
    strSQL2 = Replace(strSQL, "xxxx", rstLocal!PointNumber) 
    strSQL2 = Replace(strSQL2, "zzzz", rstLocal!FullName) 
    qdfPass.SQL = strSQL2 
    qdfPass.Execute 
    rstLocal.MoveNext 
    Loop 

    rstLocal.Close