跳转至

使用odbc驱动

使用ODBC

本章节给出了一些使用ODBC的简单示例,你可以从中了解在几种常见的编程语言中如何使用ODBC驱动来访问数据库。

从C#中访问

需要的环境准备

  • C# 编译器

  • Microsoft .NET Framework

  • Microsoft ODBC .NET Data Provider.

  • SeaboxSQL数据库源

下面的代码可能需要根据实际环境进行适当的修改才能工作,用于示例的表数据如下

CREATE TABLE vbtest(
    id serial,
    data text,
    accessed timestamp
);
INSERT INTO csharptest(data, accessed) VALUES('Rows: 1', now());
INSERT INTO csharptest(data, accessed) VALUES('Rows: 2', now());
INSERT INTO csharptest(data, accessed) VALUES('Rows: 3', now());

通过ODBC访问数据的代码

using System;
using System.Data;
using Microsoft.Data.Odbc;
 
class ssqlODBC_Howto
{
  [STAThread]
  static void Main(string[] args)
  {

    // Setup a connection string
    string szConnect = "DSN=dsnname;" +
                       "UID=seabox;" +
                       "PWD=********";

    // Attempt to open a connection
    OdbcConnection cnDB = new OdbcConnection(szConnect);
     
    // The following code demonstrates how to catch & report an ODBC exception.
    // To keep things simple, this is the only exception handling in this example.
    // Note: The ODBC data provider requests ODBC3 from the driver. At the time of
    //       writing, the ssqlODBC driver only supports ODBC2.5 - this will cause
    //       an additional error, but will *not* throw an exception.
    try 
    {
      cnDB.Open();
    } 
    catch (OdbcException ex) 
    {
      Console.WriteLine (ex.Message + "\n\n" + "StackTrace: \n\n" + ex.StackTrace);
      // Pause for the user to read the screen.
      Console.WriteLine("\nPress  to continue...");
      Console.Read();
      return;
    }
    
    // Create a dataset
    DataSet dsDB = new DataSet(); 
    OdbcDataAdapter adDB = new OdbcDataAdapter();
    OdbcCommandBuilder cbDB = new OdbcCommandBuilder(adDB);
    adDB.SelectCommand = new OdbcCommand(
                             "SELECT id, data, accessed FROM csharptest", 
                             cnDB);
    adDB.Fill(dsDB);

    // Display the record count
    Console.WriteLine("Table 'csharptest' contains {0} rows.\n", 
                      dsDB.Tables[0].Rows.Count);
    
    // List the columns (using a foreach loop)
    Console.WriteLine("Columns\n=======\n");
    
    foreach(DataColumn dcDB in dsDB.Tables[0].Columns)
      Console.WriteLine("{0} ({1})", dcDB.ColumnName, dcDB.DataType);
    Console.WriteLine("\n");

    // Iterate through the rows and display the data in the table (using a for loop).
    // Display the data column last for readability.
    Console.WriteLine("Data\n====\n");
    for(int i=0;i to continue...");
    Console.Read();
  }
}

从C/C++中访问

需要的环境准备

  • Ch标准版或专业版

  • Ch ODBC Toolkit

  • IODBC, UNIXODBC或者Microsoft ODBC管理器

  • SeaboxSQL数据库源

如何在Ch中执行ODBC代码

你可以在Ch Shell环境中执行下面的simple.c脚本

% ch
                                   Ch 
                  Standard edition, version 4.0.0.11291 
              (C) Copyright 2001-2003 SoftIntegration, Inc.
                     http://www.softintegration.com
/home/wcheng> cd $CHHOME/package/iodbc/demos
/usr/local/ch/package/iodbc/demos> ls
odbctest.c  simple.c
/usr/local/ch/package/iodbc/demos> ./simple.c
SQLAllocHandle() OK
SQLSetEnvAttr() ok
SQLAllocHandle() ok
SQLSetConnectAttr() ok
/usr/local/ch/package/iodbc/demos> cat simple.c

/**************************** simple.c *****************************/ 
#include <sqlext.h>
#include <stdio.h>

void ODBC_error (       /* Get and print ODBC error messages */
    SQLHENV henv,       /* ODBC Environment */
    SQLHDBC hdbc,       /* ODBC Connection Handle */
    SQLHSTMT hstmt)     /* ODBC SQL Handle */
{
    UCHAR   sqlstate[10];
    UCHAR   errmsg[SQL_MAX_MESSAGE_LENGTH];
    SDWORD  nativeerr;
    SWORD   actualmsglen;
    RETCODE rc = SQL_SUCCESS;

    while ( rc != SQL_NO_DATA_FOUND)
    {
        rc = SQLError(henv, hdbc, hstmt,
                      sqlstate, &nativeerr, errmsg,
                      SQL_MAX_MESSAGE_LENGTH - 1, &actualmsglen);
                     
         if (rc == SQL_ERROR) {
              printf ("SQLError failed!\n");
              return;
         }

         if (rc != SQL_NO_DATA_FOUND) {
               printf ("SQLSTATE = %s\n", sqlstate);
               printf ("NATIVE ERROR = %d\n", nativeerr);
               errmsg[actualmsglen] = '\0';
               printf ("MSG = %s\n\n", errmsg);
          }
     }
     if (hdbc != SQL_NULL_HDBC)
     {
        SQLFreeHandle (SQL_HANDLE_DBC, hdbc);
     }
     if (henv != SQL_NULL_HENV)
     {
        SQLFreeHandle (SQL_HANDLE_ENV, henv);
     }
}

int main(void)
{
    SQLHENV henv = SQL_NULL_HENV;
    SQLHDBC hdbc = SQL_NULL_HDBC;
    SQLHSTMT hstmt = SQL_NULL_HSTMT;
    RETCODE  rc    = SQL_SUCCESS;

    rc = SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);

    if (rc != SQL_ERROR)
    {
        printf("SQLAllocHandle() OK\n");
        rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,0);
        if (rc != SQL_ERROR)
        {
            printf("SQLSetEnvAttr() ok\n");
            rc = SQLAllocHandle (SQL_HANDLE_DBC, henv, &hdbc);
            if ( rc != SQL_ERROR)
            {
                 printf("SQLAllocHandle() ok\n");
                 rc = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF,0);
                 if (rc != SQL_ERROR)
                 {
                       printf("SQLSetConnectAttr() ok\n");
                       SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
                       SQLFreeHandle(SQL_HANDLE_ENV, henv);
                 }
             }
         }
     }

     if (rc == SQL_ERROR)
     {
         ODBC_error (henv, hdbc, hstmt);
     }
}

从VBA中访问

下面是一段用VBA通过ODBC驱动访问Seabox数据据库的方法。 特别使用编程的方式链接和取消链接MS Access数据库中的SeaboxSQL关系。 代码中通过注释对各个步骤进行了解释,它包含两个子例程,一个子例程链接一个新关系,另一个子例程取消链接。

如何在VBA中执行ODBC代码

Private Sub Link_ODBCTbl(serverConn As String, rstrTblSrc As String, _
                         rstrTblDest As String, db As Database) 
LogEvent "Entering " & APP_NAME & ": Form_Login.Link_ODBCTbbl(" & _
         rstrTblSrc & ")", etDebug 
On Error GoTo Err_Handler

StartWork "Adding relation: " & rstrTblSrc

    Dim tdf As TableDef
    Dim connOptions As String
    Dim myConn As String
    Dim myLen As Integer
    Dim bNoErr As Boolean

    bNoErr = True

    Set tdf = db.CreateTableDef(rstrTblDest)
    ' don't need next line, as only called if doesn't exist locally
    'db.TableDefs.Delete rstrTblDest 
    ' this is 1st error, as doesn't exist locally yet; maybe wrong key


' The length of the connection string allowed is limited such that you can't 
' specify all of the SeaboxSQL ODBC driver options as you normally would. 
' For those that want to do it normally, you are limited to somewhere between 
' 269 characters (works) and 274 (doesn't work). Using a dsn is not a workaround. 
' 
' ***WORKAROUND*** Tested Access 2000 on Win2k, SeaboxSQL on Red Hat 7.2 
' 
' The connection string begins as usual, for example: 
'
'   "ODBC;DRIVER={SeaboxSQL};DATABASE=database_name_to_connect_to;" & _
'   "SERVER=ip_address_to_connect_to;PORT=5432;Uid=username_to_connect_as;" & _
'   "Pwd=password_of_user;" & _ 
' 
' For all other parameters, you must code them in the same way Access stores them 
' in the hidden MSysObjects table.  Here is a cross-reference table: 
' 
'   SD_ODBC_PARAMETER           ACCESS_PARAMETER
'   *********************************************
'   READONLY                    A0
'   PROTOCOL                    A1
'   FAKEOIDINDEX                A2  'A2 must be 0 unless A3=1
'   SHOWOIDCOLUMN               A3
'   ROWVERSIONING               A4
'   SHOWSYSTEMTABLES            A5
'   CONNSETTINGS                A6
'   FETCH                       A7
'   SOCKET                      A8
'   UNKNOWNSIZES                A9  ' range [0-2]
'   MAXVARCHARSIZE              B0
'   MAXLONGVARCHARSIZE          B1
'   DEBUG                       B2
'   COMMLOG                     B3
'   OPTIMIZER                   B4  ' note that 1 = _cancel_ generic optimizer...
'   KSQO                        B5
'   USEDECLAREFETCH             B6
'   TEXTASLONGVARCHAR           B7
'   UNKNOWNSASLONGVARCHAR       B8
'   BOOLSASCHAR                 B9
'   PARSE                       C0
'   CANCELASFREESTMT            C1
'   EXTRASYSTABLEPREFIXES       C2
'
' So the parameter part of the connection string might look like: '
'   "A0=0;A1=6.4;A2=0;A3=0;A4=0;A5=0;A6=;A7=100;A8=4096;A9=0;" & _
'   "B0=254;B1=8190;B2=0;B3=0;B4=1;B5=1;B6=0;B7=1;B8=0;B9=1;C0=0;C1=0;C2=dd_"
'
' Concatenating those four strings together will give you a working connection  
' string (but you may want to change the options specified). 
' 
' NOTES:
'   `Disallow Premature` in driver dialog is not stored by Access.
'   string must begin with `ODBC;` or you will get error
'   `3170 Could not find installable ISAM`.

'Debug.Print svr.Conn

myConn = "ODBC;DRIVER={SeaboxSQL};" & serverConn & _
            "A0=0;A1=6.4;A2=0;A3=0;A4=0;A5=0;A6=;A7=100;A8=4096;A9=0;" & _
            "B0=254;B1=8190;B2=0;B3=0;B4=1;B5=1;B6=0;B7=1;B8=0;B9=1;" & _
            "C0=0;C1=0;C2=dd_"

    tdf.Connect = myConn
    tdf.SourceTableName = rstrTblSrc
    db.TableDefs.Append tdf
    db.TableDefs.Refresh

    ' If we made it this far without errors, table was linked...
    If bNoErr Then
        LogEvent "Form_Login.Link_ODBCTbl: Linked new relation: " & _
                 rstrTblSrc, etDebug
    End If

    'Debug.Print "Linked new relation: " & rstrTblSrc ' Link new relation

    Set tdf = Nothing

Exit Sub

Err_Handler:
    bNoErr = False
    Debug.Print Err.Number & " : " & Err.Description
    If Err.Number <> 0 Then LogError Err.Number, Err.Description, APP_NAME & _
                                     ": Form_Login.Link_ODBCTbl"
    Resume Next

End Sub

Private Sub UnLink_ODBCTbl(rstrTblName As String, db As Database) 
LogEvent "Entering " & APP_NAME & ": Form_Login.UnLink_ODBCTbbl", etDebug 
On Error GoTo Err_Handler

    StartWork "Removing revoked relation: " & rstrTblName

    ' Delete the revoked relation...that'll teach 'em not to get on my bad side
    ' I only call this sub after verifying the relation exists locally, so I 
    ' don't check if it exists here prior to trying to delete it, however if you 
    ' aren't careful...
    db.TableDefs.Delete rstrTblName
    db.TableDefs.Refresh

    Debug.Print "Removed revoked relation: " & rstrTblName

Exit Sub

Err_Handler:
    Debug.Print Err.Number & " : " & Err.Description
    If Err.Number <> 0 Then LogError Err.Number, Err.Description, APP_NAME & _
                                     ": Form_Login.UnLink_ODBCTbl"
    Resume Next

End Sub

从Visual Basic中访问

需要的环境准备

  • Visual Basic 6或更高版本

  • 在VB项目中存在到Microsoft ActiveX数据对象的连接

  • SeaboxSQL数据库源

下面的代码可能需要根据实际环境进行适当的修改才能工作,用于示例的表数据如下

CREATE TABLE vbtest( 
    id int4,
    data text,
    accessed timestamp
);

如何在Visual Basic中执行ODBC代码

Sub Main()
Dim cn as New ADODB.Connection
Dim rs as New ADODB.Recordset
 
  'Open the connection
  cn.Open "DSN=<MyDataSourceName>;" & _
          "UID=<MyUsername>;" & _
          "PWD=<MyPassword>;" & _
          "Database=<MyDatabaseName>"
 
  'Clear the table
  cn.Execute "DELETE FROM vbtest;"
  
  'For updateable recordsets we would typically open a Dynamic recordset.
  'Forward Only recordsets are much faster but can only scroll forward and 
  'are read only. Snapshot recordsets are read only, but scroll in both 
  'directions. 
  rs.Open "SELECT id, data, accessed FROM vbtest", cn, adOpenDynamic, adLockOptimistic
 
  'Loop though the recordset and print the results
  'We will also update the accessed column, but this time access it through 
  'the Fields collection. ISO-8601 formatted dates/times are the safest IMHO.
  While Not rs.EOF
    Debug.Print rs!id & ": " & rs!data
    rs.Fields("accessed") = Format(Now, "yyyy-MM-dd hh:mm:ss")
    rs.Update
    rs.MoveNext
  Wend
 
  'Add a new record to the recordset
  rs.AddNew
  rs!id = 76
  rs!data = 'More random data'
  rs!accessed = Format(Now, "yyyy-MM-dd hh:mm:ss")
  rs.Update

  'Insert a new record into the table
  cn.Execute "INSERT INTO vbtest (id, data) VALUES (23, 'Some random data');"

  'Refresh the recordset to get that last record...
  rs.Requery

  'Get the record count
  rs.MoveLast
  rs.MoveFirst
  MsgBox rs.RecordCount & " Records are in the recordset!"

  'Cleanup
  If rs.State <> adStateClosed Then rs.Close
  Set rs = Nothing
  If cn.State <> adStateClosed Then cn.Close
  Set cn = Nothing
End Sub

函数调用

' The escapeString function can be used to fix strings for us in INSERT and 
' UPDATE SQL statements. It will take a value, and return it ready for 
' use in your statement as NULL, or quoted with backslashes and single quotes
' escaped.

Function escapeString(vValue As Variant) As String

  If IsNull(vValue) Then
    escapeString = "NULL"
  else
    escapeString = "'" & Replace(Replace(vValue, "", ""), "'", "''") & "'" 
  end if

End Function