PRB: Decimal Values Passed to a Stored Procedure Get Truncated
ID: Q188574
|
The information in this article applies to:
-
ActiveX Data Objects (ADO), versions 1.0, 1.5, 2.0, 2.1 SP2
-
Microsoft Visual Basic Enterprise Edition for Windows, versions 4.0, 5.0, 6.0
SYMPTOMS
Values passed into a Stored Procedure may lose their decimal values.
CAUSE
This depends on the ability of the backend server to define constraints or
numeric scale for arguments used by a stored procedure. This is possible
under SQL Server, but it is not a feature in Oracle.
RESOLUTION
If you are using Oracle and Remote Data Objects (RDO) the workaround is to
change the Parameters Type property to rdNumeric. If you are using ActiveX Data Objects (ADO) and Oracle, define an appropriate Parameter object(s) and set the Parameter's NumericScale property accordingly.
Under SQL Server a numeric scale or a constraint must be defined on the
stored procedures parameter. If this is defined, then decimal values will
be received by the stored procedure. If the parameters are not defined with
numeric scale then the decimal values will be truncated.
STATUS
This behavior is by design.
MORE INFORMATION
Steps to Reproduce Behavior
- Use the following sample SQL Server Scripts to generate the stored procedures and table. The first stored procedure illustrates the problem. The second stored procedure demonstrates how to define input parameters with numeric scale:
if exists (select * from sysobjects where id =
object_id('dbo.numericscale') and sysstat & 0xf = 3
drop table dbo.numericscale
GO
CREATE TABLE dbo.numericscale (
mynum numeric(5, 2) NULL ,
mydec decimal(5, 2) NULL
)
GO
if exists (select * from sysobjects where id =
object_id('dbo.SimpleSQL1') and sysstat & 0xf = 4)
drop procedure dbo.SimpleSQL1
GO
CREATE PROCEDURE SimpleSQL1 @input1 numeric, @input2 decimal
AS
INSERT into numericscale values (@input1, @input2)
GO
if exists (select * from sysobjects where id =
object_id('dbo.SimpleSQL2') and sysstat & 0xf = 4)
drop procedure dbo.SimpleSQL2
GO
CREATE PROCEDURE SimpleSQL2 @input1 numeric(5,2), @input2
decimal(5,2)
AS
INSERT into numericscale values (@input1, @input2)
GO
The Visual Basic ADO code for calling the stored procedures is shown in
step 3 below.
- Add a reference to Microsoft ActiveX Data Objects in the project.
- Add the following ADO code to the default form's Load method:
Dim cn As ADODB.Connection
Dim cm1 As ADODB.Command
Dim cm2 As ADODB.Command
Dim pm1 As ADODB.Parameter
Dim pm2 As ADODB.Parameter
Dim rs as ADODB.Recordset
Set cn = New ADODB.Connection
Set cm1 = New ADODB.Command
Set cm2 = New ADODB.Command
Set pm1 = New ADODB.Parameter
Set pm2 = New ADODB.Parameter
Set rs = New ADODB.Recordset
With cn
.ConnectionString = "DRIVER={SQL SERVER};" & _
"SERVER=<server_name>;" & _
"UID=sa;PWD="
.Open
.DefaultDatabase = "pubs"
End With
With pm1
.Direction = adParamInput
.Name = "param1"
.NumericScale = 2 ' this corresponds to the second sp's numeric
' scale.
.Precision = 10
.Size = 19
.Type = adNumeric
.Value = 3.2
End With
With pm2
.Direction = adParamInput
.Name = "param2"
.NumericScale = 2
.Precision = 10
.Size = 19
.Type = adNumeric
.Value = 3.2
End With
With cm1
Set .ActiveConnection = cn
.CommandType = adCmdStoredProc
.CommandText = "simplesql1"
.Parameters.Append pm1
.Parameters.Append pm2
.Parameters(0).Value = 3.25
.Parameters(1).Value = 4.26
End With
cm1.Execute
Set cm1.ActiveConnection = nothing
With cm2
Set .ActiveConnection = cn
.CommandType = adCmdStoredProc
.CommandText = "simplesql2"
.Parameters.Append pm1
.Parameters.Append pm2
.Parameters(0).Value = 5.35
.Parameters(1).Value = 6.46
End With
cm2.Execute
Set cm1 = Nothing
Set cm2 = Nothing
Set rs = cn.Execute("select * from numericscale")
While Not rs.EOF
Debug.Print rs(0).Name & ": " & rs(0)
Debug.Print rs(1).Name & ": " & rs(1)
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
Unload Me
- Run the form.
The Visual Basic RDO code for calling the stored procedures is in step 7
below.
- Create a new Visual Basic (VB) Standard EXE project.
- Add a Project reference to Microsoft Remote Data Objects.
- Add the following code to the default form's Load method:
Dim en As rdoEnvironment
Dim cn As rdoConnection
Dim rs As rdoResultset
Dim rq1 As rdoQuery
Dim rq2 As rdoQuery
Dim val1 As Double
Dim val2 As Double
val1 = 8.2
val2 = 9.2
Set en = rdoEngine.rdoEnvironments(0)
en.CursorDriver = rdUseOdbc
Set cn = en.OpenConnection("",rdDriverNoPrompt,," & _
"DRIVER={SQL Server};" & _
"Server=matthofa;" & _
"UID=sa;PWD=;" & _
"DATABASE=pubs")
Set rq1 = cn.CreateQuery("", "{Call simplesql1(?,?) }")
rq1.rdoParameters(0).Direction = rdParamInput
rq1.rdoParameters(0).Value = val1
rq1.rdoParameters(1).Direction = rdParamInput
rq1.rdoParameters(1).Value = val2
Set rq2 = cn.CreateQuery("", "{Call simplesql2(?,?) }")
rq2.rdoParameters(0).Direction = rdParamInput
rq2.rdoParameters(0).Value = val1
rq2.rdoParameters(1).Direction = rdParamInput
rq2.rdoParameters(1).Value = val2
rq1.Execute
rq2.Execute
rq1.Close
rq2.Close
Set rs = cn.OpenResultset("select * from numericscale")
While Not rs.EOF
Debug.Print rs(0).Name & ": " & rs(0)
Debug.Print rs(1).Name & ": " & rs(1)
rs.MoveNext
Wend
cn.Close
en.Close
Unload Me
- Run the application.
Additional query words:
Keywords : kbADO kbDatabase kbMDAC kbOracle kbRDO kbRDO200 kbStoredProc kbGrpVBDB kbGrpMDAC kbDSupport kbADO210sp2 kbMDAC210SP2
Version : WINDOWS:1.0,1.5,2.0,2.1 SP2,4.0,5.0,6.0
Platform : WINDOWS
Issue type : kbprb