Guide to Migrating Sybase Application Interfaces to SQL Server 2008 SQL Server Technical Article Writers: Yuri Rusakov (DB Best Technologies), Alexander Pavlov (DB Best Technologies), Yuri Kovtun (DB Best Technologies) Technical Reviewer: Dmitry Balin (DB Best Technologies) Published: <Month/Year> Applies to: SQL Server 2008 Summary: This white paper describes methods of migrating applications with Sybase interfaces to SQL Server. We cover both Open Standard APIs (ODBC, JDBC, OLE DB, ADO.Net) and proprietary APIs (CT-Library, DB-Library). Created by: DB Best Technologies LLC P.O. Box 7461, Bellevue, WA 98008 Tel.: (408) 202-4567 E-mail: info@dbbest.com Web: www.dbbest.com Copyright This is a preliminary document and may be changed substantially prior to final commercial release of the software described herein. The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication. This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation. Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property. Unless otherwise noted, the example companies, organizations, products, domain names, email addresses, logos, people, places and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, email address, logo, person, place or event is intended or should be inferred. © 2010 Microsoft Corporation. All rights reserved. Microsoft and SQL Server are registered trademarks of Microsoft Corporation in the United States and other countries. The names of actual companies and products mentioned herein may be the trademarks of their respective owners. 2 Contents Copyright ................................................................................................................................... 2 Introduction ................................................................................................................................ 4 Conversion of Open Standard Application Interfaces ................................................................. 5 Overview ................................................................................................................................ 5 JDBC ...................................................................................................................................... 5 ODBC ..................................................................................................................................... 5 OLE DB .................................................................................................................................. 6 ADO.NET ............................................................................................................................... 8 Driver versions ....................................................................................................................... 9 Open Client Libraries to ODBC Migration ..................................................................................11 Overview ...............................................................................................................................11 Main Migration Steps .............................................................................................................11 CT-Library Schema migration ................................................................................................12 Header files mapping .........................................................................................................12 Routine mapping ................................................................................................................12 Type and structure mapping...............................................................................................17 DB-Library Schema migration ................................................................................................20 Overview ............................................................................................................................20 Header files mapping .........................................................................................................20 Routine mapping ................................................................................................................20 Type and structure mapping...............................................................................................25 Other Types of Migration ...........................................................................................................27 Using FreeTDS tool to migrate CT Library and DB Library applications to SQL Server .........27 Migration of Open Client Embedded SQL ..............................................................................27 Migration of ASE Job Scheduler objects ................................................................................28 Conversion of Transact-SQL statements which are embedded in applications ......................28 Conclusion ................................................................................................................................30 About DB Best Technologies .................................................................................................30 3 Introduction DB Best Technologies, Inc. created several white papers which cover migration of databases, such as Oracle or Sybase ASE, to SQL Server 2008. However, in most of the cases there is also a necessity to change database access code in an application connecting to the migrated database. The task is easiest when the application uses a database interface designed to serve many database servers. In this white paper we discuss Open Database Connectivity (ODBC), Java Database Connectivity (JDBC), Object Linking and Embedding Database (OLE DB) and ActiveX Data Objects for .NET (ADO.NET). Migration of such interfaces can be as simple as changing the database driver and/or connection strings. More complicated are the cases when we use proprietary interfaces of one database vendor, which do not provide connectivity to SQL Server 2008. Examples are Sybase ASE CT-Library and DB-Library. In this paper we describe how to change the application code to use SQL Server compatible ODBC interface. 4 Conversion of Open Standard Application Interfaces Overview In this section we discuss methods of redirecting multi-database interfaces of Sybase Adaptive Server Enterprise (ASE) applications to SQL Server 2008. Note that the application code may contain pieces of SQL strings, which are sent to the database and which may not be compatible with SQL Server after the interface was redirected. In such cases, we should convert the embedded SQL according to the rules of SQL conversion. JDBC To convert a JDBC application, we need to change name of loaded JDBC driver class and modify its URL accordingly. Examples: JDBC connection to Sybase ASE: Class.forName(“com.sybase.jdbc.SybDrive”); String url = "jdbc:sybase:Tds:sybase_server_name:5000/test_base”; Connection dbc = DriverManager.getConnection(url, login, password); See below the changes necessary to make this code connect to SQL Server. The class name of SQL Server driver should be specified as a parameter of Class.forName() method, and getConnection method of the loaded class should follow the URL syntax for SQL Server. Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”); String url = “jdbc:sqlserver://sql_server_name:1433”; Connection dbc = DriverManager.getConnection(url, login, password); ODBC ODBC is a universal interface, which means we can change the servers just by specifying another Data Source Name. See below a typical example of switching the database in ODBC connect code. 5 ODBC connection to Sybase: SQLRETURN retcode; SQLHENV env; SQLHDBC dbc; retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env ); retcode = SQLSetEnvAttr( env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); retcode = SQLAllocHandle( SQL_HANDLE_DBC, env, &dbc ); retcode = SQLConnect(dbc, (SQLCHAR*) "sybase_DataSource_name", SQL_NTS, (SQLCHAR*) "sybase_login", SQL_NTS, (SQLCHAR*) "sybase_password", SQL_NTS); ODBC connection to SQL Server: SQLRETURN retcode; SQLHENV env; SQLHDBC dbc; retcode = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env ); retcode = SQLSetEnvAttr( env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); retcode = SQLAllocHandle( SQL_HANDLE_DBC, env, &dbc ); retcode = SQLConnect(dbc, (SQLCHAR*) "mssql_DataSource_name", SQL_NTS, (SQLCHAR*) "mssql_login", SQL_NTS, (SQLCHAR*) "mssql_password", SQL_NTS); OLE DB To establish a connection with a data source we need to create an instance of OLE DB provider, which exposes interfaces of the data source, and then to perform initialization of this instance. To do that, we should use function CoCreateInstance with OLE DB provider class ID as the first parameter. Next, we initialize the data source using array of structures DBPROP. In the simplest case, we need to specify four properties: prompt level, DSN name, user name and password. The difference between OLE DB connections for different databases is in OLE DB provider object and object initialization parameters. Connecting to Sybase ASE with OLE DB: #include "msdasql.h" 6 … IDBInitialize* pIDBInitialize = NULL; HRESULT hr; hr = CoCreateInstance(CLSID_MSDASQL, NULL, CLSCTX_INPROC_SERVER, IID_IDBInitialize, (void**)&pIDBInitialize); … InitProperties[0].dwPropertyID = DBPROP_INIT_PROMPT; InitProperties[0].vValue.vt = VT_I2; InitProperties[0].vValue.iVal = DBPROMPT_NOPROMPT; InitProperties[1].dwPropertyID = DBPROP_INIT_DATASOURCE; InitProperties[1].vValue.vt = VT_BSTR; InitProperties[1].vValue.bstrVal = SysAllocString(OLESTR("sybase_DataSource_name")); InitProperties[2].dwPropertyID = DBPROP_AUTH_USERID; InitProperties[2].vValue.vt = VT_BSTR; InitProperties[2].vValue.bstrVal = SysAllocString(OLESTR("sybase _login")); InitProperties[3].dwPropertyID = DBPROP_AUTH_PASSWORD; InitProperties[3].vValue.vt = VT_BSTR; InitProperties[3].vValue.bstrVal = SysAllocString(OLESTR("sybase _password")); Connecting to SQL Server using OLE DB: #include "msdasql.h" … IDBInitialize* pIDBInitialize = NULL; HRESULT hr; hr = CoCreateInstance(CLSID_MSDASQL, NULL, CLSCTX_INPROC_SERVER, IID_IDBInitialize, (void**)&pIDBInitialize); … InitProperties[0].dwPropertyID = DBPROP_INIT_PROMPT; InitProperties[0].vValue.vt = VT_I2; InitProperties[0].vValue.iVal = DBPROMPT_NOPROMPT; InitProperties[1].dwPropertyID = DBPROP_INIT_DATASOURCE; InitProperties[1].vValue.vt = VT_BSTR; InitProperties[1].vValue.bstrVal = SysAllocString(OLESTR("mssql_DataSource_name")); InitProperties[2].dwPropertyID = DBPROP_AUTH_USERID; InitProperties[2].vValue.vt = VT_BSTR; InitProperties[2].vValue.bstrVal = SysAllocString(OLESTR("mssql_login")); InitProperties[3].dwPropertyID = DBPROP_AUTH_PASSWORD; InitProperties[3].vValue.vt = VT_BSTR; 7 InitProperties[3].vValue.bstrVal = SysAllocString(OLESTR("mssql_password")); When using ATL library, we should choose class CDataSource for connection to a database. Databases differ by parameters of Open() method. CDataSource dsDSN; HRESULT hr; // Connecting to Sybase ASE with ATL OLE DB: hr = dsDSN.Open(_T("MSDASQL"), “sybase_DataSource_name”, "sybase_login", "sybase_password"); // Connecting to SQL Server with ATL OLE DB: hr = dsDSN.Open(_T("MSDASQL"), “mssql_DataSource_name”, "mssql_login", "mssql_password"); ADO.NET ADO.NET architecture uses data providers to access a database. There are various implementations of the .NET interfaces for different DBMSes. For example, connections to SQL Server are handled by special class SqlConnection. Each provider includes its own set of .NET framework classes in a separate namespace. When performing migration, we should replace calls to objects of one namespace to the calls of SQL Server provider. The only exception is ODBC and OLE DB providers, which by definition are compatible with multiple databases. When the original provider uses System.Data.Odbc, the Sybase to SQL Server migration may be as simple as replacement of the connection string. An example of Sybase connection: OdbcConnection connection = new OdbcConnection( "Driver={SYBASE ASE ODBC Driver};Srvr=myServerAddress;Uid=myUsername;Pwd=myPassword;"); connection.Open(); Equivalent SQL Server connection: OdbcConnection connection = new OdbcConnection( 8 "Driver={SQL Server};Server=(local);Trusted_Connection=Yes;Database=AdventureWorks; "); connection.Open(); Similarly, we replace the connection string in case of ADO.NET OLE DB provider. Sybase OLE DB connection: OleDbConnection connection = new OleDbConnection( "Provider=Sybase.ASEOLEDBProvider;Srvr=myASEserver,5000;Catalog=myData Base;User Id=myUsername;Password=myPassword;"); connection.Open(); SQL Server connection: OleDbConnection connection = new OleDbConnection( "Provider=SQLOLEDB;Server=myServerAddress;Database=myDataBase;Uid=myUs ername; Pwd=myPassword;"); connection.Open(); When the source code uses Oracle specific provider defined in System.Data.AseClient, we will need to replace the class names with their counterparts in System.Data.SqlClient. Sybase connection: AseConnection connection = new AseConnection (connectionString); connection.Open(); SQL Server connection: SqlConnection connection = new SqlConnection(connectionString); connection.Open(); Driver versions We suggest to use this driver in case of JDBC conversion: http://www.microsoft.com/downloads/details.aspx?familyid=99B21B65-E98F-4A61-B81119912601FDC9&displaylang=en You can take Microsoft SQL Server OLE DB Provider and ODBC driver from Microsoft Data Access Components (MDAC) : 9 http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=6c050fe3-c7954b7d-b037-185d0506396c ADO.NET Data Provider for SQL Server is shipped as a part of MDAC or as a part of .NET Framework. . 10 Open Client Libraries to ODBC Migration Overview Following are the basic, high-level steps for migrating a Sybase Open Client Libraries interfaces to SQL Server ODBC interface and what you must know about converting interface routines. Main Migration Steps From the point of view of the client program both Sybase Open Client and ODBC represent a set of the C modules connected to program, containing the description of necessary types and functions for use of opportunities of the corresponding interface. Base functionality of libraries is identical and realizes necessary commands for performance of operations of initialization of the driver, connection to a database server, execute SQL statement, fetching of results and closings of connection. Converting a Sybase Open Client Libraries program to its SQL Server ODBC equivalent generally involves the following steps: 1. Replace Open Client Libraries header file names with the ODBC header file names. 2. Plan the code conversion. Client application code can be split roughly into the following categories: Initialization and cleanup code; Code that opens a connection; Error and message handlers; Code that sends commands; Code that processes results; Finalization code; 3. 11 Perform the conversion: Replace or remove Open Client Libraries declarations, as appropriate. Replace Open Client Libraries function calls with their ODBC equivalents, changing program logic as necessary. CT-Library Schema migration This section explains mappings and differences between CT-Library and ODBC modules, commands and types. Header files mapping The following table displays the list of required header C files for the use CT-Library and ODBC API. CT-Library ODBC #include <ctpublic.h> #include <sql.h> #include <sqlext.h> Routine mapping The following table displays the commands, used in typical execution steps of CT-Library and ODBC applications, and their correspondence. CT-Library ODBC STEP 1: Set Up The Client-Library Programming Environment STEP 1: Connect To The Data Source cs_ctx_alloc Allocate a context structure. cs_config Set any CS-Library properties for the context. ct_init SQLAllocHandle(ENV) Initialize Client-Library. Load the Driver Manager and allocate the environment handle. Driver Manager allocates a structure in which to store information about the environment, and returns the environment handle. ct_config SQLSetEnvAttr Set Client-Library properties for the context. Sets attributes that govern aspects of environments. STEP 2: Define Error Handling 12 cs_config(CS_MESSAGE_CB) Install a CS-Library error callback. Replace with SQLGetDiagField and SQLGetDiagRec function calls in the return code handlers. SQLGetDiagField Returns the current value of a field of a record of the diagnostic data structure (associated with a specified handle) that contains error, warning, and status information. SQLGetDiagRec Returns the current values of multiple fields of a diagnostic record that contains error, warning, and status information. Unlike SQLGetDiagField, which returns one diagnostic field per call, SQLGetDiagRec returns several commonly used fields of a diagnostic record, including the SQLSTATE, the native error code, and the diagnostic message text. ct_callback Install a client or server message callback. Ct_callback installs Client-Library callback routines, which are application routines that Client-Library calls automatically when a triggering event of the appropriate type occurs. STEP 3: Connect To A Server ct_con_alloc SQLAllocHandle(DBC) Allocate a connection structure. Allocate a connection handle. Driver Manager allocates a structure in which to store information about the connection and returns the connection handle. ct_con_props SQLSetConnectAttr Set any properties in the connection structure. Sets attributes that govern aspects of connections. Some connection attributes must be set before the application attempts to connect, others can be set after the connection has completed. 13 ct_connect Open a connection to a server. SQLConnect or SQLDriverConnect or SQLBrowseConnect SQLConnect establishes connections to a driver and a data source. ct_options Set any server options for this connection. STEP 4: Send A Language Command To The Server STEP 2: Initialize The Application ct_cmd_alloc SQLAllocHandle(STMT) Allocate a command structure. Driver Manager allocates a structure in which to store information about the statement and calls SQLAllocHandle in the driver with the SQL_HANDLE_STMT option. The driver allocates its own structure in which to store information about the statement and returns the driver statement handle to the Driver Manager. The Driver Manager returns the Driver Manager statement handle. ct_cmd_props SQLSetStmtAttr Set, retrieve, or clear command structure properties. Sets attributes related to a statement. STEP 3: Build And Execute An SQL Statement ct_command SQLPrepare Define a command. Prepares an SQL string for execution. ct_param or ct_setparam SQLBindParameter Define a command parameter. Binds a buffer to a parameter marker in an SQL statement. ct_send SQLExecute Sends the command text to the server, which parses, compiles, and executes it. Executes a prepared statement, using the current values of the parameter marker variables. STEP 5: Process The Results Of The STEP 4: Fetch The Results; Fetch The 14 Command Row Count ct_results Set up result data to be processed. Defines type of command result: • Values that indicate command status; • Values that indicate fetchable results; • Values that indicate information is available. ct_res_info SQLNumResultCols Retrieve current result set or command information. Returns the number of columns in a result set. The possible returned information: If this is 0, the statement did not create a result set, if it is any other number, the statement did create a result set. • The number of the command that generated the current result set; • The number of compute clauses in the current command; • The number of items in the current result set; • The number of columns specified in the order-by clause of the current command; • The number of rows affected by the current command; SQLRowCount Returns the number of rows affected by an UPDATE, INSERT, or DELETE statement. If a batch of SQL statements is executed, the count of affected rows might be a total count for all statements in the batch or individual counts for each statement in the batch. and others. ct_describe SQLDescribeCol Return a description of result data. Returns the result descriptor — column name, type, column size, decimal digits, and nullability — for one column in the result set. An application can use ct_describe to retrieve a description of a regular result column, a return parameter, a stored procedure return status number, or a compute column. An application can call ct_res_info to find out how many result items are present in the current result set. An application generally needs to call ct_describe to describe a result data item before it binds the result item to a program variable using ct_bind. ct_bind SQLBindCol Bind server results to program variables Binds application data buffers to columns 15 When the application calls ct_fetch to fetch the result data, it is copied into this variables. in the result set. ct_fetch SQLFetch Fetch result data. Fetches the next rowset of data from the result set and returns data for all bound columns. SQLGetData Retrieves data for a single column in the result set. It can be called multiple times to retrieve variable-length data in parts. The application now calls SQLFetch to retrieve the first row of data and place the data from that row in the variables bound with SQLBindCol. If there is any long data in the row, it then calls SQLGetData to retrieve that data. The application continues to call SQLFetch and SQLGetData to retrieve additional data. After it has finished fetching data, it calls SQLCloseCursor to close the cursor. SQLCloseCursor Closes a cursor that has been opened on a statement and discards pending results. STEP 5: Commit The Transaction The application performs this step only if it set the transaction commit mode to manual-commit; if the transaction commit mode is auto-commit, which is the default, the transaction is automatically committed when the statement is executed SQLEndTran Requests a commit or rollback operation for all active operations on all statements associated with a connection. STEP 6: Finish STEP 6: Disconnect From The Data Source ct_cmd_drop SQLFreeHandle(STMT) Deallocate a command structure. Free the statement. Driver releases the 16 structure used to store information about the statement. ct_close SQLDisconnect Close a connection. Frees any statements that are allocated on the connection and disconnects the driver from the data source. ct_con_drop Deallocate connection structure. ct_exit SQLFreeHandle(DBC) Exit Client-Library for a specific context. Closes and deallocates any open connections and cleans up internal Client- Free the connection. Driver releases the structure used to store information about the connection. Library data space. cs_ctx_drop SQLFreeHandle(ENV) Deallocates a context structure. Frees the environment handle. Driver releases the structure used to store information about the environment. Type and structure mapping The following table displays the correspondence of types and structures of CT-Library to types and structures of ODBC: CT-Library ODBC Structures CS_CONTEXT HENV Context structure. Environment handle. CS_CONNECTION HDBC Connection structure. Connection handle. CS_COMMAND HSTMT Command structure. Statement handle. Types Numeric types CS_TINYINT tinyint 17 SQLSCHAR (SQL_C_STINYINT) CS_SMALLINT SQLSMALLINT (SQL_C_SSHORT) smallint CS_USMALLINT SQLUSMALLINT (SQL_C_USHORT) usmallint CS_INT SQLINTEGER (SQL_C_SLONG) int CS_UINT SQLUINTEGER (SQL_C_ULONG) uint CS_BIGINT SQLBIGINT (SQL_C_SBIGINT) bigint CS_UBIGINT SQLUBIGINT (SQL_C_UBIGINT) ubigint CS_DECIMAL SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) decimal structure CS_NUMERIC SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) numeric structure CS_FLOAT SQLDOUBLE, SQLFLOAT (SQL_C_DOUBLE) float CS_REAL SQLREAL (SQL_C_FLOAT) real Money types CS_MONEY SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) money structure CS_MONEY4 SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) smallmoney structure Character types CS_CHAR SQLCHAR (SQL_C_CHAR) char varchar CS_UNICHAR SQLWCHAR (SQL_C_WCHAR) unichar univarchar Datetime types CS_DATE SQL_DATE_STRUCT (SQL_C_TYPE_DATE) date structure CS_TIME SQL_TIME_STRUCT (SQL_C_TYPE_TIME) time structure CS_DATETIME SQL_TIMESTAMP_STRUCT (SQL_C_TYPE_TIMESTAMP) datetime structure CS_DATETIME4 18 SQL_TIMESTAMP_STRUCT smalldatetime (SQL_C_TYPE_TIMESTAMP) structure Bit types CS_BIT SQLCHAR (SQL_C_BIT) bit Binary types CS_BINARY binary varbinary SQLCHAR (SQL_C_BINARY) Text and image types CS_TEXT SQLCHAR (SQL_C_CHAR) text CS_UNITEXT SQLWCHAR (SQL_C_WCHAR) unitext CS_IMAGE image 19 SQLCHAR (SQL_C_BINARY) DB-Library Schema migration Overview This section explains mappings and differences between DB-Library and ODBC modules, commands and types. Header files mapping The following table displays the list of required header C files for the use DB-Library and ODBC API. DB-Library ODBC #include <sybfront.h> #include <sql.h> #include <sybdb.h> #include <sqlext.h> #include <syberror.h> Routine mapping The following table displays the commands, used in typical execution steps of DB-Library and ODBC applications, and their correspondence. DB-Library ODBC STEP 1: Initialization STEP 1: Connect To The Data Source dbinit() SQLAllocHandle(ENV) Initialize DB-Library. Load the Driver Manager and allocate the environment handle. Driver Manager allocates a structure in which to store information about the environment, and returns the environment handle. dbsetversion(dbproc, version) SQLSetEnvAttr Specify the version level for desired behavior. Sets attributes that govern aspects of environments. STEP 2: Define Error Handling dberrhandle(handler) Install DB-Library error callback function. dbmsghandle(handler) Install DB-Library server message callback function. 20 Replace with SQLGetDiagField and SQLGetDiagRec function calls in the return code handlers. SQLGetDiagField Returns the current value of a field of a record of the diagnostic data structure (associated with a specified handle) that contains error, warning, and status information. SQLGetDiagRec Returns the current values of multiple fields of a diagnostic record that contains error, warning, and status information. Unlike SQLGetDiagField, which returns one diagnostic field per call, SQLGetDiagRec returns several commonly used fields of a diagnostic record, including the SQLSTATE, the native error code, and the diagnostic message text. STEP 3: Connect To A Server dblogin() SQLAllocHandle(DBC) Allocate a LOGINREC for use in dbopen. Allocate a connection handle. Driver Manager allocates a structure in which to store information about the connection and returns the connection handle. DBSETLUSER(loginrec, username) SQLSetConnectAttr Set the username in the LOGINREC structure. Sets attributes that govern aspects of connections. Some connection attributes must be set before the application attempts to connect, others can be set after the connection has completed. DBSETLPWD(loginrec, password) Set the user server password in the LOGINREC structure. DBSETLAPP(loginrec, application) Set the application name in the LOGINREC structure. dbopen(loginrec, server) Connect to a server (and allocate the DBPROCESS). STEP 4: Send A Language Command To The Server SQLConnect or SQLDriverConnect or SQLBrowseConnect SQLConnect establishes connections to a driver and a data source. STEP 2: Initialize The Application SQLAllocHandle(STMT) Driver Manager allocates a structure in which to store information about the statement and calls SQLAllocHandle in the driver with the SQL_HANDLE_STMT option. The driver allocates its own structure in 21 which to store information about the statement and returns the driver statement handle to the Driver Manager. The Driver Manager returns the Driver Manager statement handle. SQLSetStmtAttr Sets attributes related to a statement. STEP 3: Build And Execute An SQL Statement dbfcmd(dbproc, string, args...) SQLPrepare Format text and add to the DBPROCESS command buffer. Prepares an SQL string for execution. dbcmd(dbproc, string) Add text to the DBPROCESS command buffer. dbrpcinit(dbproc, rpc_name, option) Initialize an RPC. dbrpcparam(dbproc, paramname, status, type, maxlen, datalen, data) SQLBindParameter Add a parameter to an RPC. Binds a buffer to a parameter marker in an SQL statement. dbsqlexec(dbproc) SQLExecute Send a command batch to the server for execution. Executes a prepared statement, using the current values of the parameter marker variables. dbrpcsend(dbproc) Send an RPC call to the server for execution. STEP 5: Process The Results Of The Command STEP 4: Fetch The Results; Fetch The Row Count dbresults Sets up the results of the next query. dbnumalts SQLNumResultCols Returns the number of columns in a compute row. Returns the number of columns in a result set. If this is 0, the statement did not create a result set, if it is any other number, the statement did create a result set. dbnumcols Determines the number of regular columns for the current set of results. dbnumrets Determines the number of return parameter 22 SQLRowCount Returns the number of rows affected by an values generated by a stored procedure. DBCOUNT Returns the number of rows affected by a Transact-SQL command. DBCURCMD UPDATE, INSERT, or DELETE statement. If a batch of SQL statements is executed, the count of affected rows might be a total count for all statements in the batch or individual counts for each statement in the batch. Returns the number of the current logical command. dbaltlen SQLDescribeCol Returns the maximum length of the data for a particular compute column. Returns the result descriptor — column name, type, column size, decimal digits, and nullability — for one column in the result set. dbalttype Returns the datatype for a compute column. dbaltutype Returns the user-defined datatype for a compute column. dbcollen Returns the maximum length of the data in a regular result column. dbcolname Returns the name of a regular result column. dbcoltype Returns the datatype for a regular result column. dbcolutype Returns the user-defined datatype for a regular result column. dbretname Determines the name of the stored procedure parameter associated with a particular return parameter value. dbrettype Determines the datatype of a return parameter value generated by a stored procedure. dbaltbind, dbaltbind_ps SQLBindCol Binds a compute column to a program variable. Binds application data buffers to columns in the result set. dbbind, dbbind_ps Binds a regular result column to a program variable. 23 dbnextrow SQLFetch Reads the next result row. Fetches the next rowset of data from the result set and returns data for all bound columns. SQLGetData Retrieves data for a single column in the result set. It can be called multiple times to retrieve variable-length data in parts. The application now calls SQLFetch to retrieve the first row of data and place the data from that row in the variables bound with SQLBindCol. If there is any long data in the row, it then calls SQLGetData to retrieve that data. The application continues to call SQLFetch and SQLGetData to retrieve additional data. After it has finished fetching data, it calls SQLCloseCursor to close the cursor. SQLCloseCursor Closes a cursor that has been opened on a statement and discards pending results. STEP 5: Commit The Transaction The application performs this step only if it set the transaction commit mode to manualcommit; if the transaction commit mode is auto-commit, which is the default, the transaction is automatically committed when the statement is executed SQLEndTran Requests a commit or rollback operation for all active operations on all statements associated with a connection. STEP 6: Cleanup STEP 6: Disconnect From The Data Source SQLFreeHandle(STMT) Free the statement. Driver releases the structure used to store information about the statement. dbclose(dbproc) SQLDisconnect Close and deallocate a DBPROCESS structure. Frees any statements that are allocated on the connection and disconnects the driver from the data source. 24 dbexit() SQLFreeHandle(DBC) Close and deallocate all DBPROCESS structures and clean up any structures initialized by dbinit. Free the connection. Driver releases the structure used to store information about the connection. SQLFreeHandle(ENV) Frees the environment handle. Driver releases the structure used to store information about the environment. Type and structure mapping The following table displays the correspondence of types and structures of DB-Library to types and structures of ODBC: DB-Library ODBC Structures LOGINREC HDBC Contains typical login information Connection handle DBPROCESS HSTMT Through the DBPROCESS, commands are sent to the server and query results are returned to the application Statement handle Types Numeric types SYBINT1 SQLSCHAR (SQL_C_STINYINT) 1-byte integer SYBINT2 SQLSMALLINT (SQL_C_SSHORT) 2-byte integer SYBINT4 SQLINTEGER (SQL_C_SLONG) 4-byte integer SYBDECIMAL SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) decimal type structure SYBNUMERIC SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) numeric type structure SYBFLT8 SQLDOUBLE, SQLFLOAT (SQL_C_DOUBLE) 25 8-byte float type SYBREAL SQLREAL (SQL_C_FLOAT) 4-byte float type Money types SYBMONEY money type SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) structure SYBMONEY4 SQL_NUMERIC_STRUCT (SQL_C_NUMERIC) 4-byte money type structure Character types SYBCHAR SQLCHAR (SQL_C_CHAR) char type Datetime types SYBDATETIME datetime type SQL_TIMESTAMP_STRUCT (SQL_C_TYPE_TIMESTAMP) structure SYBDATETIME4 4-byte datetime type SQL_TIMESTAMP_STRUCT (SQL_C_TYPE_TIMESTAMP) structure Bit types SYBBIT SQLCHAR (SQL_C_BIT) bit type Binary types SYBBINARY SQLCHAR (SQL_C_BINARY) binary type Text and image types SYBTEXT SQLCHAR (SQL_C_CHAR) text type SYBIMAGE image type 26 SQLCHAR (SQL_C_BINARY) Other Types of Migration This section covers migration of several Sybase features related to application programming and products using connection to Sybase. Using FreeTDS tool to migrate CT Library and DB Library applications to SQL Server FreeTDS libraries can be used for redirecting Sybase client applications to SQL Server. FreeTDS provides implementations of DB-Library, CT-Library and ODBC driver, allowing many Sybase client applications that use these interfaces to communicate with Microsoft SQL Server. You can download the source code for FreeTDS from the Web site (http://www.freetds.org) and then build, install, and configure it for your target platform. Take into account that FreeTDS is an open source project and is still very much a work in progress. Although much of the core functionality is available, you may find it necessary to either implement any missing functionality in the FreeTDS libraries that your application requires, or modify your application to avoid these features. Migration of Open Client Embedded SQL Sybase Embedded SQL is a superset of Transact-SQL that lets place Transact-SQL statements in application programs written in C. Open Client Embedded SQL enables to create programs that access and update Adaptive Server data. Embedded SQL programmers write SQL statements directly into an application program written in C. A preprocessing program — the Embedded SQL precompiler — processes the completed application program, resulting in a program that the host language compiler can compile. The program is linked with Open Client Client-Library before it is executed. Embedded SQL is one of the two programming methods Sybase provides for accessing Adaptive Server. The other programming method is the call-level interface. With the call-level interface, you place Client-Library calls directly into an application program, then link with ClientLibrary. Embedded SQL statements can be placed anywhere in a host program and mixed with host language statements. All Embedded SQL statements must begin with the keywords EXEC SQL and end with a semicolon (;). After you write an Embedded SQL program, run it through the precompiler, which translates the Embedded SQL statements into Client-Library function calls. 27 To migrate Sybase C application with Embedded SQL on SQL Server, we suggest replace Open Client Embedded SQL statements with ODBC routine calls. Migration of ASE Job Scheduler objects The SQL Server counterpart of Sybase ASE Job Scheduler is the SQL Server Agent jobs. Like Sybase Job Scheduler the SQL Server Agent allows you to create and schedule jobs, and to share jobs and schedules. At the same time SQL Server Agent provides more functionality to job and schedule management. You can use SQL Server Agent jobs to automate routine administrative tasks and run them on a recurring basis, making administration more efficient. A job is a specified series of operations performed sequentially by SQL Server Agent. A job can perform a wide range of activities, including running Transact-SQL scripts, command-line applications, Microsoft ActiveX scripts, Integration Services packages, Analysis Services commands and queries, or Replication tasks. Jobs can run repetitive tasks or those that can be scheduled, and they can automatically notify users of job status by generating alerts, thereby greatly simplifying SQL Server administration. You can run a job manually, or you can configure it to run according to a schedule or in response to alerts. Conversion of Transact-SQL statements which are embedded in applications You can use the Statements branch in SSMA for Sybase to convert SQL strings embedded in the user's application code by executing the following steps: 1. In Sybase tree, select the required database and schema and execute Add Statement command from the Statements branch context menu to create new Statement window. 2. Cut the statement from the application (or reconstruct it if the statement is built according to an algorithm). 3. Paste it into the Statement window. 4. Execute Convert Schema. 5. Paste the result back into the proper place in the application code. 28 Temporary tables in code can create problems when their definitions are absent in the module you are converting. Generally, you should convert the module where a temporary table is created before converting the modules from which the temporary table is referenced. That way, SSMA is able to remember the table definition and to use it properly. 29 Conclusion This migration guide can give you some hints about migration of Sybase-based applications to SQL Server. We discussed typical solutions for most commonly used Sybase application interfaces. About DB Best Technologies DB Best Technologies is a leading provider of database and application migration services and custom software development. We have been focused on heterogeneous database environments (SQL Server, Oracle, Sybase, DB2, MySQL) since starting at 2002 in Silicon Valley. Today, with over 75 employees in the United States and Europe, we develop database tools and provide services to customers worldwide. DB Best developed migration tools to automate conversion between SQL dialects. In 2005 Microsoft acquired this technology, which later became a family of SQL Server Migration Assistant (SSMA) products. We continue to develop new versions of SSMA, and support Microsoft customers who are migrating to SQL Server. We also provide migration services covering all major steps of a typical migration project: complexity assessment, schema conversion, data migration, application conversion, testing, integration, deployment, performance tuning, training, and support. For more details, visit us at www.dbbest.com, e-mail us at info@dbbest.com, or call 1-408-2024567. For more information: http://www.microsoft.com/sqlserver/: SQL Server Web site http://technet.microsoft.com/en-us/sqlserver/: SQL Server TechCenter http://msdn.microsoft.com/en-us/sqlserver/: SQL Server DevCenter Did this paper help you? Please give us your feedback. Tell us on a scale of 1 (poor) to 5 (excellent), how would you rate this paper and why have you given it this rating? For example: Are you rating it high due to having good examples, excellent screen shots, clear writing, or another reason? Are you rating it low due to poor examples, fuzzy screen shots, or unclear writing? This feedback will help us improve the quality of white papers we release. Send feedback. 30