When linking a program that uses SQLAPI++ I got an error: unresolved external symbol "__declspec(dllimport) public: virtual __thiscall ..."
What is missing?

Probably you forgot to include sqlapi.lib (or other SQLAPI++ library, depends on the compiler and/or static/dynamic version) into the project. To link with SQLAPI++ library you have to include sqlapi.lib into you project (as well as *.cpp)

For example, in Visual C++ you have to do the following:

  1. In workspace tree select the project that you link with SQLAPI++
  2. Use "Add Files to Project..." command on the right click menu and add sqlapi.lib to you project
  3. Press F7 button to compile and link you project
  • sqlapi.lib should be used when linking with dynamic version of SQLAPI++ using Microsoft Visual C++
  • sqlapis.lib to link with a static version using MSVC++
  • sqlapib.lib to link with a dynamic version using Borland C++ compiler
  • sqlapibs.lib to link with a static version using Borland C++ compiler
  • sqlapibb.lib to link with a dynamic version using Borland C++ Builder compiler
  • sqlapibbs.lib to link with a static version using Borland C++ Builder compiler
  • To link with a debug version use appropriate lib file that ends with 'd'
Sybase Stored Procedure
How can I get status return code from stored procedure on Sybase?

SQLAPI++ library automatically creates SAParam object to represent procedure status return code.

After a command execution you can check it value. This SAParam object's name is "RETURN_VALUE", object's type is SA_dtLong, object's direction type is SA_ParamReturn.

Sybase Stored Procedure
I have a stored procedure in Sybase ASE that has an input-output parameter. But when I call SAParam::ParamDirType method for this parameter it always returns SA_ParamInput, and when I try to get the parameter's value after the command execution I receive nothing.
What is wrong?

Sybase ASE server does not provide information about parameter's direction type, that's why SQLAPI++ library defines all parameters (except status result code) as input (SA_ParamInput). If you have input-output parameters in the procedure you have to call SAParam::setParamDirType method for these parameters before command execution and set parameter's direction type explicitly (SA_ParamInputOutput).

You shouldn't call this method for procedure status result code because it is detected correctly (as SA_ParamReturn) by the library.

There is no need to call this method for Sybase ASA because all parameters are detected correctly automatically (including the direction type).

Sybase Connection
Sometimes "sybinit.err" file is appended to at a successful SQLAPI++ connection to ASE/ASA using Open Client? Console application also outputs some warning(s) about context allocation failure.
Is this indicative of a real problem I should worry about?

SQLAPI++ has to set the version of Client-Library behavior when it connects to Sybase. By default SQLAPI++ tries to set 12.5 behavior; if it fails, SQLAPI++ tries to set 11.0 behavior and so on from the highest version to the lowest one until it succeeds. Finally the connection is successful, but every time when it fails Sybase server generates the appropriate error message and adds the same error message to the "sybinit.err" file.

The solution is to set the CS_VERSION option to "Detect" using SAConnection::setOption method. In that case SQLAPI++ automatically detects the maximum available version of behavior via the version of Client-Library.

I execute a "Select..." statement and then call SACommand::RowsAffected() method to determine the number of rows to be returned by the command, but the result is always incorrect (-1 or 0 most of the times).
What is wrong?
SACommand::RowsAffected is only applicable to INSERT/UPDATE/DELETE queries. It is database API limitation, not SQLAPI++'s. The only way to get to know result set size in advance is to execute "Select count(*)..." command.
Linking Visual Studio
When linking a program that uses SQLAPI++ under Microsoft Visual Studio 2005 I got an error: error LNK2001: unresolved external symbol "public: __thiscall SAString::SAString(wchar_t const *)"
I do include sqlapiu.lib in the project. What's wrong?

We provide SQLAPI++ binaries that are linked with Microsoft Visual Studio 6. Visual C++ 2005 compiler turns the /Zc:wchar_t option on by default. This is incompatible with Visual C++ 6.

To avoid this problem you can turn off /Zc:wchar_t option (use /Zc:wchar_t- or look at the project options dialog ('Treat wchar_t as Build-in Type' item).

But the best option is to rebuild SQLAPI++ with Visual C++ 2005 compiler.

Linking Visual Studio
When linking a program with static SQLAPI++ library I got an error: sqlapis.lib(samisc.obj) : error LNK2019: unresolved external symbol _GetFileVersionInfoA@16 referenced in function "void * __cdecl SAGetVersionInfo(char const *)" (?SAGetVersionInfo@@YAPAXPBD@Z)
Do I need to include additional libraries to resolve this?
Since SQLAPI++ 3.7.25 you also need the libraries: user32.lib, version.lib, oleaut32.lib and ole32.lib
SQL Server Connection Linux
How can I connect to Microsoft SQL Server from Linux using SQLAPI++?

There is an SQL Server ODBC/SQLNCLI Driver for Linux that provides native connectivity from Linux to Microsoft SQL Server.

SQLAPI++ support this client software but Microsoft releases this driver only for x86-64 Linux platforms. When you want to run the software on 32-bit Linux or any other Unix-like system you must use ODBC connection. You need ODBC driver manager (most known are iODBC or unixODBC) and MSSQL ODBC driver (FreeTDS ODBC driver or commercial EasySOFT one).

You must install and configure ODBC software. Often Linux distribution maintainers split the software into several packages, for example Debian Lenny includes the next iODBC and FreeTDS packages:

  • iodbc - GTK+ config frontend for the iODBC Driver Manager
  • libiodbc2-dev - iODBC Driver Manager (development files)
  • libiodbc2 - iODBC Driver Manager
  • freetds-common - configuration files for FreeTDS SQL client libraries
  • freetds-dev- MS SQL and Sybase client library (static libs and headers)
  • libct4 - libraries for connecting to MS SQL and Sybase SQL servers
  • libsybdb5 - libraries for connecting to MS SQL and Sybase SQL servers
  • tdsodbc - ODBC driver for connecting to MS SQL and Sybase SQL servers

It's enough to have installed only iodbc, libiodbc2, freetds-common and tdsodbc packages. For the first time it's better to configure and test DSN (any driver manager includes console tool for command line SQL):

bedlam:~# cat ~/.odbc.ini
[ODBC Data Sources]
MSSQL = FreeTDS driver
Driver = /usr/lib/odbc/
Database = pubs
TDS_Version = 7.0

bedlam:~# cat ~/.odbcinst.ini
[ODBC Drivers]
FreeTDS driver = Installed
[FreeTDS driver]
Driver = /usr/lib/odbc/
Setup = /usr/lib/odbc/

iodbc package provides iodbctest tool I run with parameters to check the ODBC DSN status:

bedlam-home:~# iodbctest "DSN=MSSQL;UID=sa;PWD=xxx"
iODBC Demonstration program
This program shows an interactive SQL processor
Driver Manager: 03.52.0607.1008
Driver: 0.82 (


Then you can connect using SQLAPI++:

con.Connect("MSSQL", "sa", "xxx", SA_ODBC_Client);

or without DSN configured:

conn.Connect("DRIVER={FreeTDS driver};SERVER=BEDLAM-M\SQLEXP2008EN;DATABASE=pubs;TDS_Version=7.0", "sa", "xxx", SA_ODBC_Client);

Is there a way to get the number of rows returned by a query?
Generally it's impossible. Most DBMS can count the result set rows only when all rows are already cached at the client side. For such cases SACommand::RowsAffected method returns the result set row count.
Source Code Windows
I got the .diff files, but how can I apply them to my existing source code? Could you please help me?

You need a GNU patch tool. Version for Win32 can be downloaded from SouceForge. Then run it from the console like:

C:\SQLAPI\src>patch.exe < myClient.cpp.diff
patching file myClient.cpp

Linking Linux
When compiling step1.cpp on Linux got an error: undefined reference to `dlerror', 'dlopen', 'dlsym'...
Could you help?

SQLAPI++ uses libdl library API to load DBMS API. So you should include this library when you linking your binary file with SQLAPI, e.g.:

g++ -I../inclide -L../lib step1.cpp -o step1.out -lsqlapi -ldl

or with static SQLAPI without libpath:

g++ -I../inclide step1.cpp -o step1.out ../lib/libsqlapi.a -lsqlapi -ldl

MySQL SACommand SAConnection
Could I have multiple instances of SACommand in one SAConnection? I tested under MySQL database, keep SACommands being opened, and always get error "Commands out of sync; you can't run this command now".

Default MySQL API doesn't allow to have several opened result set per connection. This is exactly what mysql_use_result does. The connection is blocked until you fetch all result set rows. When you'd like to run another command when there is not fetched result set at the same connection you must use another solution. The simplest - using MySQL 'store' result set:

SACommand cmd(&con, "select ...");
cmd.setOption("HandleResult") = "store";

Then SQLAPI uses mysql_store_result and all rows cached at he client side after query is executed and you can fetch the result and execute another command at the same connection. The not good thing - this solution uses local MySQL client data cache. So MySQL guys added another feature - statement API. statement API allows to execute command but the result set stored at the client side. SQLAPI++ can use this feature with 'SELECT' commands. The limitation - the single, forward-only result set only:

SACommand cmd(&con, "select ...");
cmd.setOption("UseStatement") = "TRUE";

SQL Server SACommand SAConnection
I am getting the error "HY000 [Microsoft][SQL Server Native Client 11.0] Connection is busy with results for another command".
"I have 1 SAConnection object and 2 SACommand objects. One of the SACommand objects is simply stepping through the records in a table. The second object is attempting to INSERT a new record into the same table, before we have processed all of the records in the first command.
Is this not allowed or am I doing something wrong?"

This is known SQL Server issue. SQL Server doesn't allow to have the several result sets at the same connection by default (the same problem is actual also for Sybase ASE, MySQL, ...). The possible solutions for SQL Server:

  • using MARS_Connection option. This is global option for the connection. You can turn it on like:
    SAConnection con;
    con.Connect(_TSA("bedlam-m\\sql2014en@test;MARS_Connection=yes"), _TSA(""),
    _TSA(""), SA_SQLServer_Client);
  • using the server side cursor for executing SACommand:
    SACommand cmd(&con, _TSA("select ..."));
isAlive isConnected
Could you please tell me what is the difference between isAlive and isConnected? How to use them properly?

See below the simplified usage scenario:

            // database operations below
        catch(SAException& x)
                    try {
                    } catch(SAException&) {