Calling Sql Server 2008 stored procedure from vb6 with datetime - sql-server-2008

I have a legacy vb6 app which accesses databases running on both SQL2000 and SQL2008 databases.
When calling a stored procedure with a datetime parameter from vb6 using an adDBTimeStamp input parameter, the complete date time, including seconds is passed to the stored procedure.
When calling the same stored procedure in an SQL2008 r2 database, the seconds are always zero.
EDIT:
Create the following stored procedure on both a SQL2000 database and an SQL2008 R2 database.
CREATE PROCEDURE [dbo].[TestDate] (#DateAndTime DATETIME)
AS
SET NOCOUNT ON
BEGIN
SELECT #DateAndTime AS DateAndTime
END
Then build a VB6 app with the following command button event method:
Private Sub Command_Click()
Dim SQL2000_ConnectionString As String
Dim SQL2008_ConnectionString As String
Dim DateOnly As Date
Dim DateAndTime As Date
DateAndTime = DateTime.Now
SQL2000_ConnectionString = "Driver={SQL Server};Server=<SQL2000ServerName>;UID=<UserName>;pwd=<Password>;Database=<DataBaseName>;dsn=''"
SQL2008_ConnectionString = "Provider=SQLNCLI10;DataTypeCompatibility=80;Server=<SQL2008ServerName>;Database=<DataBaseName>;User Id=<UserName>;Password=<Password>;"
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim Msg As String
Set conn = New ADODB.Connection
conn.ConnectionTimeout = 300
Call conn.Open(SQL2000_ConnectionString)
Set cmd = New ADODB.Command
With cmd
.CommandType = adCmdStoredProc
Set .ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "TestDate"
.CommandTimeout = 60
Call .Parameters.Append(.CreateParameter("#dtDateAndTime", adDBTimeStamp, adParamInput))
.Parameters("#dtDateAndTime").Value = DateAndTime
Set rs = .Execute
End With
If Not rs.EOF Then
Msg = "DateTime:" & rs.fields("DateAndTime").Value
Call MsgBox(Msg)
End If
Call conn.Close
Set conn = New ADODB.Connection
conn.ConnectionTimeout = 300
Call conn.Open(SQL2008_ConnectionString)
Set cmd = New ADODB.Command
With cmd
.CommandType = adCmdStoredProc
Set .ActiveConnection = conn
.CommandType = adCmdStoredProc
.CommandText = "TestDate"
.CommandTimeout = 60
Call .Parameters.Append(.CreateParameter("#dtDateAndTime", adDBTimeStamp, adParamInput))
.Parameters("#dtDateAndTime").Value = DateAndTime
Set rs = .Execute
End With
If Not rs.EOF Then
Msg = "DateTime:" & rs.fields("DateAndTime").Value
Call MsgBox(Msg)
End If
Call conn.Close
End Sub
When you execute the vb6 app, the first message box displays with the date and time including seconds. The second message box has the seconds display as zero.
I am seeing the same thing when I log the input parameters within the databases.
It appears as though the call to the SQL2008 R2 database is truncating the seconds of the input parameter.
2nd EDIT:
It appears that the OLE DB driver may be the culprit.
When I change to use the Native Client, it appears to work correctly.
SQL2008_ConnectionString = "Driver={SQL Server Native Client 10.0};Server=<SQL2008ServerName>;UID=<UserName>;pwd=<Password>;Database=<DataBaseName>;"
As this is a heavily used legacy app, and regression testing everything to use a new driver is time prohibitive. Is there any way to make the OLE DB driver do the correct thing?
3rd EDIT:
Just realized it is not a SQL 2008 R2 box. I was mistaken. It is just SQL2008
Here is my ##VERSION:
Microsoft SQL Server 2008 (SP3) - 10.0.5500.0 (X64) Sep 21 2011 22:45:45 Copyright (c) 1988-2008 Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (VM)

I found the solution.
Apparently the solution is to set the precision and numeric scale on the command object parameter to that of the defined size of addbTimeStamp.
Adding these two lines to the cmd object parameter before the call to the SQL2008 database, and the seconds are passed to the stored procedure.
.Parameters("#dtDateAndTime").Precision = 23
.Parameters("#dtDateAndTime").NumericScale = 3

Related

How to Connect to an Access Database Using VBScript

I have an Access database for a client who wants to connect to and query the database using vbscript (so they can automate without actually opening the Access 2000 MDB). I can't figure out how to make the database connection.
I've tried several scripts, using both DAO and OLEDB. Below I've pasted the closest I've got, using an ODBC File DSN (I'm afraid using a System DSN would require extra work on the client's end, I'm trying to keep it simple).
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordset = CreateObject("ADODB.Recordset")
'ERROR OCCURS HERE
objConnection.Open "FileDSN=D:\RLS.dsn;"
objRecordset.CursorLocation = adUseClient
objRecordset.Open "SELECT County FROM CountyTBL" , objConnection, adOpenStatic, adLockOptimistic
Here is the contents of RLS.dsn (I created this using Windows Control Panel so I am confident it's correct):
[ODBC]
DRIVER=Microsoft Access Driver (*.mdb)
UID=admin
UserCommitSync=Yes
Threads=3
SafeTransactions=0
PageTimeout=5
MaxScanRows=8
MaxBufferSize=2048
FIL=MS Access
DriverId=25
DefaultDir=D:\
DBQ=D:\RLS_be.mdb
The error message I got (and this was similar with the other 2 scripts I tried as well) was:
"Line 5, Char 4 Error: [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified. Source: Microsoft OLE DB Provider for ODBC Drivers"
You can simply use ADO to connect to the file without setting up a DSN. This will be simpler for your client.
For Access 2000, 2002-2003 MDB, use the following connection string:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\RLS_be.mdb"
For Access 2007, 2010, 2013 ACCDB:
"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=D:\RLS_be.accdb"
The overall connection code:
' Build connection string
Dim sConnectionString
sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\RLS_be.mdb"
' Create connection object
Dim objConnection
Set objConnection = CreateObject("ADODB.Connection")
' Open Connection
objConnection.open sConnectionString
' Get recordset from SQL query
Dim objRecordset
Dim sQuery
sQuery = "SELECT County FROM CountyTBL"
Set objRecordset = CreateObject("ADODB.Recordset")
objRecordset.CursorLocation = adUseClient
objRecordset.Open sQuery, objConnection, adOpenStatic, adLockOptimistic
Here is another version using the connection string for a MS-Access 2016 database. The example connects to the 'clients.accdb' database and retrieves the value of the 'ClientID' field of the record where the 'ClientName' is equal to 'Joe Smith', then it loops through the records returned by the SQL statement.
Note that the extra quotations in the SQL statement are used in order to handle the scenario in which the name might contain a single quot ('), for example O'Connor.
Dim oConn, oRS
Dim ClientName : ClientName = "Joe Smith"
Set oConn = WSH.CreateObject("ADODB.Connection")
oConn.Open "Provider=Microsoft.ACE.OLEDB.16.0; Data Source=C:\test\clients.accdb"
Set oRS = oConn.Execute("Select ClientID From Clients Where ClientName=""" & ClientName & """")
Do While Not(oRS.EOF)
'Do something with the record.
oRS.MoveNext
Loop
oRS.Close
oConn.Close

Execute MySQL stored procedure with parameters in Access frontend via VBA

So, database hotchpotch.
I have a MySQL database which has stored procedures.
I have an Access document which is linked to the MySQL database (I can survey tables) serving as a frontend (with forms and stuff)
I have successfully created a ODBC Pass Through Query (I think that's what they are called) to call one of the stored procedures from the database. The query in Access actually is just CALL myProcName; and gives me the results I expect when I call it from VBA with Set Result = CurrentDb.OpenRecordset("myProcName")
What I am trying to achieve is the following:
Have a stored procedure in MySQL that takes one parameter => check!
Have that stored procedure working as expected => checked in phpMyAdmin => check!
Have a saved query in Access which links to this parametric stored procedure with a fixed parameter value given => check! (CALL myProcName('myParameterValue'), I can call that from VBA just as I do the unparametric query)
Have the ability to specify 'myParameterValue' everytime I execute the query => not check
I need to somehow specify a parameter placeholder in the SQL definition of the saved query and set that parameter in VBA. For the VBA part I have and idea I would find rather elegant:
Private Sub ParametricQuery()
Dim QDef As QueryDef
Set QDef = CurrentDb.QueryDefs("myProcName")
QDef.Parameters(*insert parameter name here*) = parameter value
Dim Result As Recordset
Set Result = QDef.OpenRecordset
Do While Not Result.EOF
MsgBox Result.Fields(1) 'Display a field from the results
Loop
End Sub
But how would I build my SQL definition?
PARAMETERS in_param TEXT;
CALL myProcName(in_param);
does NOT work. If I try
Set QDef = CurrentDb.QueryDefs("myProcName")
MsgBox QDef.Parameters.Count
I get a Messagebox telling me there is a total of 0 parameters in my query definition, so that doesn't work.
What I have found online is a lot of people building the actual SQL in VBA via string operations. That makes me shudder for so many reasons (security, maintainability and elegance among them). I firmly believe that there is a better way, hopefully along the lines I have sketched above. The only problem is: How to do it?
Consider using ADO for a parameterized query to call your stored procedure. Currently, you are using DAO (Access' default database API) to access a pass-thru query (a saved Access querydef). However, this type of query does not see anything in the frontend, only the backend RDMS particularly the MySQL SQL dialect and its connected database objects. Hence, you cannot bind local parameter values to it. And PARAMETERS clause is only part of the Access SQL dialect and will fail MySQL syntax.
MySQL Stored Procedure
CREATE PROCEDURE `mystoredproc`(IN param VARCHAR(254))
BEGIN
SELECT * FROM table WHERE field=param;
END
ADO Parameterized Query
Public Sub CallMySQLProc()
Dim conn As Object, cmd As Object, rst As Object
Const adCmdStoredProc = 4, adParamInput = 1, adVarChar = 200
Set conn = CreateObject("ADODB.Connection")
Set rst = CreateObject("ADODB.Recordset")
' DSN-LESS CONNECTION
conn.Open "Driver={MySQL ODBC 5.3 Unicode Driver};host=hostname;database=databasename;" _
& "UID=username;PWD=****"
' CONFIGURE ADO COMMAND
Set cmd = CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandText = "mystoredproc"
.CommandType = adCmdStoredProc
.CommandTimeout = 15
End With
' APPEND NAMED PARAM
cmd.Parameters.Append cmd.CreateParameter("param", adVarChar, _
adParamInput, 254, "some.name#example.com")
Set rst = cmd.Execute
' FREE RESOURCES
rst.Close
Set rst = Nothing
Set cmd = Nothing
Set conn = Nothing
End Sub
DAO Dynamic Pass-Through Query
Here, you can build the querydef's .SQL statement dynamically, but will not be parameterized:
Private Sub ParametricQuery()
Dim QDef As QueryDef
Dim Result As Recordset
Set QDef = CurrentDb.QueryDefs("PassThruQ")
QDef.SQL = "CALL mystoredproc('some.name#example.com')"
Set Result = QDef.OpenRecordset
Do While Not Result.EOF
Debug.Print Result.Fields(1) 'Print to immediate window a field from the results
Loop
Result.close
Set Result = Nothing
Set QDef = Nothing
End Sub

MySQL Sample for Visual Basic 6.0 - read/write

I'd like to find a simple example of working with remote MySQL base. I know, there are some tutorial over the internet, explaining how to set up ADODB.Connection and connectionstrings, but I couldnt make it work. Thanks for any help!
Download the ODBC connector from the MySQL download page.
Look for the right connectionstring over here.
In your VB6 project select the reference to Microsoft ActiveX Data Objects 2.8 Library. It's possible that you have a 6.0 library too if you have Windows Vista or Windows 7. If you want your program to run on Windows XP clients too than your better off with the 2.8 library. If you have Windows 7 with SP 1 than your program will never run on any other system with lower specs due to a compatibility bug in SP1. You can read more about this bug in KB2517589.
This code should give you enough information to get started with the ODBC connector.
Private Sub RunQuery()
Dim DBCon As adodb.connection
Dim Cmd As adodb.Command
Dim Rs As adodb.recordset
Dim strName As String
'Create a connection to the database
Set DBCon = New adodb.connection
DBCon.CursorLocation = adUseClient
'This is a connectionstring to a local MySQL server
DBCon.Open "Driver={MySQL ODBC 5.1 Driver};Server=localhost;Database=myDataBase; User=myUsername;Password=myPassword;Option=3;"
'Create a new command that will execute the query
Set Cmd = New adodb.Command
Cmd.ActiveConnection = DBCon
Cmd.CommandType = adCmdText
'This is your actual MySQL query
Cmd.CommandText = "SELECT Name from Customer WHERE ID = 1"
'Executes the query-command and puts the result into Rs (recordset)
Set Rs = Cmd.Execute
'Loop through the results of your recordset until there are no more records
Do While Not Rs.eof
'Put the value of field 'Name' into string variable 'Name'
strName = Rs("Name")
'Move to the next record in your resultset
Rs.MoveNext
Loop
'Close your database connection
DBCon.Close
'Delete all references
Set Rs = Nothing
Set Cmd = Nothing
Set DBCon = Nothing
End Sub

ms access - return records from sql Stored procedure

I have an access 2010 and I want to call a sql stored proc on a sql 2008 server and return the results to a recordset or bind directly to a report.
The method below returns the error "feture not available in ADP" or something like that - It works with a Form but not with a Report.
How do I go about doing this?
Dim cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim cm As New ADODB.Command
'Use the ADO connection that Access uses
Set cn = CurrentProject.AccessConnection
With cn
.Provider = "Microsoft.Access.OLEDB.10.0"
.Properties("Data Provider").Value = "SQLOLEDB"
.Properties("Data Source").Value = "dsidsw923"
.Properties("Integrated Security").Value = "SSPI"
.Properties("Initial Catalog").Value = "Promotions_Dev_DSI"
.Open
End With
'Create an instance of the ADO Recordset class, and
'set its properties
Set rs = New ADODB.Recordset
With cm
.ActiveConnection = cn
.CommandText = "spCheckProdWkConsist"
.CommandType = adCmdStoredProc
Set rs = .Execute()
End With
'Set the form's Recordset property to the ADO recordset
Set Me.Recordset = rs
Set rs = Nothing
Set cn = Nothing
Set cm = Nothing
Consider creating a view to wrap the results of the stored procedure (exec usp_whatever) and then create a linked table to the new view.
Also, you may be able to create a passthrough query (exec usp_whatever) that executes your stored procedure and returns your results directly. Then just bind your report or form to the query.

How to execute stored procedure from Access using linked tables

I have an Access 2003 database that connects to a SQL Server 2008 box via ODBC. The tables from SQL Server are connected as linked tables in Access. I have a stored procedure on the SQL Server that I am trying to execute via ADO code. The problem I have is that Access cannot seem to find the procedure. What do I have to do within Access to be able to execute this stored procedure? Some facts ...
The stored procedure in question accepts one parameter which is an integer. The stored procedure returns a recordset which I am hoping to use as the datasource for a ListBox.
Here is my ADO code in Access ...
Private Sub LoadUserCaseList(userID As Integer)
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.ActiveConnection = CurrentProject.Connection
cmd.CommandType = adCmdStoredProc
cmd.CommandText = "uspGetUserCaseSummaryList"
Dim par As New ADODB.Parameter
Set par = cmd.CreateParameter("userID", adInteger)
cmd.Parameters.Append par
cmd.Parameters("userID") = userID
Dim rs As ADODB.Recordset
Set rs = cmd.Execute()
lstUserCases.Recordset = rs
End Sub
The error I get is "the microsoft jet database engine cannot find the input table or query "uspGetUserCaseSummaryList".
CurrentProject.Connection is the connection to your Access database. You can verify that by doing this in the Immediate window:
Debug.Print CurrentProject.Connection
You need to create a new ADODB.Connection object with a connection string which points to your SQL Server instance. Have your ADODB.Command object use that connection.
Edit: You can eliminate the ADODB.Command object, and use the Execute method of the connection to return records from your stored procedure. This example uses a stored procedure which expects 3 parameters.
Private Sub GetCenterCodes()
Dim cnn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cnn = New ADODB.Connection
cnn.ConnectionString = "Provider=SQLOLEDB;Data Source=VM2003\sqlexpress;" _
& "User ID=foo;Password=bar;Initial Catalog=Inventory"
cnn.Open
Set rs = New ADODB.Recordset
Set rs = cnn.Execute("EXEC uspGetCenterCodes 14, 14, 501")
Debug.Print rs(0), rs(1), rs(2)
rs.Close
Set rs = Nothing
cnn.Close
Set cnn = Nothing
End Sub
You can find a connection string example which matches your needs at ConnectionStrings.com