无法使用 unixODBC 连接到 Oracle 19

Cannot connect to Oracle 19 with unixODBC

我正在尝试使用 unixODBC 2.3.7 连接到 Oracle 19 数据库。 我正在使用 Oracle Developer Days VirtualBox VM。

尝试通过 isql 进行故障排除时,我总是收到此错误:

# isql -v -3 oracledsn

[HY000][unixODBC][Oracle][ODBC][Ora]ORA-12545: Connect failed because target host or object does not exist
[ISQL]ERROR: Could not SQLConnect

遗憾的是我现在无法重现它,但上次尝试时我总是有

[IM004][unixODBC][Driver Manager]Driver's SQLAllocHandle on SQL_HANDLE_HENV failed
[ISQL]ERROR: Could not SQLConnect

这与我从我的(专有)C++ 代码中得到的错误消息相同,所以我很确定问题出在连接设置上。

我检查了 https://www.connectionstrings.com/oracle/,但 none 的组合有效。

这是我所有的配置设置:

# odbcinst -j                                                                                                                                            -130-

unixODBC 2.3.7
DRIVERS............: /usr/local/etc/odbcinst.ini
SYSTEM DATA SOURCES: /usr/local/etc/odbc.ini
FILE DATA SOURCES..: /usr/local/etc/ODBCDataSources
USER DATA SOURCES..: /home/florian/.odbc.ini
SQLULEN Size.......: 8
SQLLEN Size........: 8
SQLSETPOSIROW Size.: 8
# cat /usr/local/etc/odbcinst.ini

[oraclex]
Description     = Oracle ODBC driver for Oracle 19
Driver          = /mnt/libsqora.so.19.1
Setup           =
FileUsage       =
CPTimeout       =
CPReuse         =
Driver Logging  = 7

[ODBC]
Trace      = Yes
TraceFile  = /tmp/odbc.log
ForceTrace = Yes
Pooling    = No
DEBUG      = 1
# cat ~/.odbc.ini 

[oracledsn]
Driver = oraclex
Server = 10.1.6.19
Port = 1521
Uid = system
Pwd = oracle
Database = orclcdb/orcl/"<empty>"

ORA-12545: 连接失败,因为目标主机或对象不存在

我也试过了ServerName

ServerName = //10.1.6.19/orclcdb or //10.1.6.19/orcl
[28000][unixODBC][Oracle][ODBC][Ora]ORA-01017: invalid username/password; logon denied

这是 /tmp/odbc.log:

[ODBC][18832][1564563250.044774][__handles.c][460]
                Exit:[SQL_SUCCESS]
                        Environment = 0x1fd7780
[ODBC][18832][1564563250.044854][SQLSetEnvAttr.c][189]
                Entry:
                        Environment = 0x1fd7780
                        Attribute = SQL_ATTR_ODBC_VERSION
                        Value = 0x3
                        StrLen = 0
[ODBC][18832][1564563250.044886][SQLSetEnvAttr.c][381]
                Exit:[SQL_SUCCESS]
[ODBC][18832][1564563250.044914][SQLAllocHandle.c][377]
                Entry:
                        Handle Type = 2
                        Input Handle = 0x1fd7780
[ODBC][18832][1564563250.044944][SQLAllocHandle.c][493]
                Exit:[SQL_SUCCESS]
                        Output Handle = 0x1fd8090
[ODBC][18832][1564563250.044983][SQLConnect.c][3721]
                Entry:
                        Connection = 0x1fd8090
                        Server Name = [oracledsn][length = 9 (SQL_NTS)]
                        User Name = [NULL]
                        Authentication = [NULL]
                UNICODE Using encoding ASCII 'ANSI_X3.4-1968' and UNICODE 'UCS-2LE'

                DIAG [HY000] [Oracle][ODBC][Ora]ORA-12545: Connect failed because target host or object does not exist


[ODBC][18832][1564563250.082037][SQLConnect.c][4244]
                Exit:[SQL_ERROR]
[ODBC][18832][1564563250.082070][SQLGetDiagRec.c][677]
                Entry:
                        Connection = 0x1fd8090
                        Rec Number = 1
                        SQLState = 0x7fffeabcac60
                        Native = 0x7fffeabcac5c
                        Message Text = 0x7fffeabcac70
                        Buffer Length = 500
                        Text Len Ptr = 0x7fffeabcac5a
[ODBC][18832][1564563250.082092][SQLGetDiagRec.c][726]
                Exit:[SQL_SUCCESS]
                        SQLState = HY000
                        Native = 0x7fffeabcac5c -> 12545
                        Message Text = [[unixODBC][Oracle][ODBC][Ora]ORA-12545: Connect failed because target host or object does not exist

我也一直在尝试 https://www.easysoft.com/developer/languages/c/odbc_tutorial.html#connect_full 中的这段 C 代码 - 结果基本相同。

# cat test2.c
#   compile with gcc -I ../include test2.c -o test2 -lodbc

#include <stdio.h>                                                              
#include <sql.h>                                                                
#include <sqlext.h>                                                             

/*                                                                              
 * see Retrieving ODBC Diagnostics                                              
 * for a definition of extract_error().                                         
 */                                                                             
static void extract_error(                                                      
    char *fn,                                                                   
    SQLHANDLE handle,                                                           
    SQLSMALLINT type);                                                          

main() {                                                                        
  SQLHENV env;                                                                  
  SQLHDBC dbc;                                                                  
  SQLHSTMT stmt;                                                                
  SQLRETURN ret; /* ODBC API return status */                                   
  SQLCHAR outstr[1024];                                                         
  SQLSMALLINT outstrlen;                                                        

  /* Allocate an environment handle */                                          
  SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);                        
  /* We want ODBC 3 support */                                                  
  SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);          
  /* Allocate a connection handle */                                            
  SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);                                    
  /* Connect to the DSN mydsn */                                                
  ret = SQLDriverConnect(dbc, NULL, "DSN=oracledsn;", SQL_NTS,                  
                         outstr, sizeof(outstr), &outstrlen,                    
                         SQL_DRIVER_COMPLETE);                                  
  if (SQL_SUCCEEDED(ret)) {                                                     
    printf("Connected\n");                                                      
    printf("Returned connection string was:\n\t%s\n", outstr);                  
    if (ret == SQL_SUCCESS_WITH_INFO) {                                         
      printf("Driver reported the following diagnostics\n");                    
      //extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);                 
    }                                                                           
    SQLDisconnect(dbc);               /* disconnect from driver */              
  } else {                                                                      
    fprintf(stderr, "Failed to connect\n");                                     
    //extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);                   
  }                                                                             
  /* free up allocated handles */                                               
  SQLFreeHandle(SQL_HANDLE_DBC, dbc);                                           
  SQLFreeHandle(SQL_HANDLE_ENV, env);                                           
}

作为另一点参考,我可以通过 sqlplus 从另一台机器连接到所述 Oracle Dev VM,如下所示:

./sqlplus sys/oracle@10.1.6.19/orclcdb as sysdba

SQL>

./sqlplus system/oracle@10.1.6.19/orclcdb

SQL>

我在 VM 上有一个文件 /u01/app/oracle/product/version/db_1/network/admin/tnsnames.ora,但我不确定客户端是否也需要一个文件?

ORCLCDB=localhost:1521/orclcdb
ORCL=
 (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orcl)
    )
  )

我终于找到了解决方案,虽然这是针对 12.2.0.1 而不是 19

# cat .odbc.ini
[oracledsn]                                                                     
Driver=oracle                                                                 
UID=system
PWD=oracle
DBQ=192.168.178.32:1521/ORCLCDB
ServerName=//192.168.178.32:1521/ORCLCDB
cat /usr/local/etc/odbcinst.ini
[oracle]
Description = foo
Driver = /mnt/libsqora.so.19.1
Driver Logging = 7
UsageCount=1
FileUsage=1

[ODBC]
Trace = Yes
TraceFile = /tmp/odbc.log
ForceTrace = Yes
Pooling = No
# LD_LIBRARY_PATH=. isql -v oracledsn system oracle
+---------------------------------------+
| Connected!                            |

没有设置特定于 Oracle 的环境变量,但是如果我为 TWO_TASK 逐字取 ServerName 的值,它是否有效。