On 28-Sep-2005 Lee Anne Lester wrote:
> Thanks for the suggestions.  Because of issues with date formats and
> also the fact that SQLDescribeParam is based on ordinal position and not
> name, the default binding behavior will not always work for us.  Also,
> we are trying to avoid having everything default to varchar.

I am tempted to ask what the issues you refer to are. The only one I know
about is the NULL issue Brian Becker reported in July - for which I posted a
patch for DBD::ODBC to this group.

Brian did seem to indicate at the time you were setting odbc_default_bind_type
- which also prevents DBD::ODBC from calling SQLDescribeParam.

> Is it
> possible the patch you are suggesting will be implemented in a future
> release of the DBD::ODBC module?

You can always lobby Jeff and he will probably lobby me for a proper patch.
But there is the previous patch (I refer to above) as well and I think that
didn't end up anywhere because after presenting the problem and a fix being
provided, odbc_default_bind_type was introduced.

Martin
--
Martin J. Evans
Easysoft Ltd, UK
Development


> Lee Anne
> 
> -----Original Message-----
> From: Martin J. Evans [mailto:[EMAIL PROTECTED] 
> Sent: Wednesday, September 28, 2005 5:18 AM
> To: Lee Anne Lester
> Cc: dbi-users@perl.org
> Subject: RE: Numeric value out of range error
> 
> On 27-Sep-2005 Lee Anne Lester wrote:
>> I am getting a "Numeric value out of range error" when specifically 
>> binding a placeholder for a decimal column as a decimal type. I'm 
>> using DBD::ODBC connecting to Microsoft SQL Server from a Solaris
> machine.
>> The value being bound is 10.00.  The settings in database are
> precision
>> 5 and a scale 2.   I have found that I don't get the error as long as
>> there are no numbers to the left of the decimal.  Example:  A value of
>> .5 works.
>> 
>> Can anyone advise how to make this work?  Is there a way to define the
> 
>> precision and scale when calling bind_param?
>> 
>> Thanks in advance for any help.
>> 
>> Lee Anne Lester
>> 
>> 
> SQL> create table jaeb (FieldDecimal numeric(5,2)) insert into jaeb 
> SQL> values ('10.00') insert into jaeb values (10.00) select * from jaeb
> +-------------+
>| FieldDecimal|
> +-------------+
>| 10.00       |
>| 10.00       |
> +-------------+
> SQLRowCount returns 2
> 2 rows fetched
> 
> So you can insert without binding OK but as you say:
> 
>#!/usr/local/bin/perl -w
> use DBI;
> my $dbh = DBI->connect('dbi:ODBC:test', 'Martin_Evans', 'easysoft'); my
> $sql = q/insert into jaeb values (?)/; my $sth = $dbh->prepare($sql);
> $sth->bind_param(1, 10.00, {TYPE=>3}); $sth->execute();
> 
> fails.
> 
> Changing the bind_param to remove the forcing the type to SQL_NUMERIC
> 
> $sth->bind_param(1, 10.00);
> 
> appears to insert correctly but a string "10" is still passed in (I'd
> presume this is because 10.00 is converted to "10").
> Passing 10.98 also works correctly. In these cases the parameter is
> bound as SQL_C_CHAR, SQL_VARCHAR.
> 
> The actual problem appears to be:
> 
> SQLBindParameter(0x8258ea0,1,1(Input::),1,3,5,5,0x82580f0,5,0x82580d0)
> 
> i.e. bind parameter 1 as input, ValueType=SQL_C_CHAR,
> ParameterType=SQL_NUMERIC, ColumnSize=5, DecimalDigits=5. This instructs
> MS SQL Server to convert your SQL_C_CHAR string into a numeric 5,5
> before inserting - this will not fit.
> 
> Interestingly, your trace shows "cbColDef=2, scale=2," and I cannot
> reproduce this.
> 
> The problem is that you are saying this parameter must be a SQL_NUMERIC
> but there is no way to specify a scale and DBD::ODBC does not use
> SQLDescribeParam when you force a bind type.
> 
> This could be changed to work but it is not a 5 minute job to do
> properly. The patch (to _dbd_rebind_ph) below makes it work but it is a
> bit of a hack:
> 
>          case SQL_TIME:
>          case SQL_TYPE_TIME:
>             /* fSqlType = SQL_VARCHAR;*/
>             break;
> +         case SQL_NUMERIC:
> +         case SQL_DECIMAL:
> +          
> +              if (phs->sv_buf && *phs->sv_buf) {
> +                   char *cp;
> +                 cp = strchr(phs->sv_buf, '.');
> +                 if (cp) {
> +                      ibScale = 0;
> +                      cp++;
> +                      while (*cp != '\0' && isdigit(*cp)) {
> +                          cp++;
> +                          ibScale++;
> +                      }
> +                 }
> +               }
> +            break;
>          case SQL_TIMESTAMP:
>          case SQL_TYPE_TIMESTAMP:
> 
> 
> Why not just pass your parameters in as strings and leave the parameter
> type off the bind call.
> 
> Martin
> --
> Martin J. Evans
> Easysoft Ltd, UK
> Development
> 
> 
>> SAMPLE CODE
>> =============
>>#!/usr/local/bin/perl -Tw
>> 
>> use strict;
>> use DBI;
>> 
>> my $dsn = "dbi:ODBC:dsn_IRB";
>> 
>> our $dbh = DBI->connect($dsn, '', '', {AutoCommit=>0, RaiseError=>1, 
>> FetchHashKeyName=>'NAME_uc'});
>> 
>> unlink('dbitrace.log') if(-e 'dbitrace.log');
>> 
>> DBI->trace(9, 'dbitrace.log');
>> 
>> my $sth = $dbh->prepare(q{INSERT INTO tblDecimalTest (FieldDecimal) 
>> VALUES (?)});
>> 
>> $sth->bind_param(1, 10.00, {TYPE=>3} );
>> 
>> $sth->execute();
>> 
>> $sth->finish;
>> 
>> $dbh->commit;
>> 
>> $dbh->disconnect;
>> ~
>> 
>> 
>> 
>> VERSIONS
>> =========
>> 
>> Microsoft SQL Server  2000 - 8.00.2039 (Intel X86) 
>>       May  3 2005 23:18:38 
>>       Copyright (c) 1988-2003 Microsoft Corporation
>>       Standard Edition on Windows NT 5.0 (Build 2195: Service Pack 4)
>> 
>> unixODBC version: 2.2.7 using EasySoft ODBC bridge
>> 
>> Perl Version = 5.008007
>> DBI Version = 1.48
>> DBD::ODBC Version = 1.13
>> 
>> 
>> OUTPUT FROM TRACE - LEVEL 9
>> ============================
>>     DBI 1.48-nothread default trace level set to 0x0/9 (pid 5169)
>>     >> prepare     DISPATCH (DBI::db=HASH(0x25300c) rc1/1 @2 g0
> ima2201
>> pid#5169) at ./insert.pl line 14
>>     -> prepare for DBD::ODBC::db (DBI::db=HASH(0x25300c)~0x260a18 
>> 'INSERT INTO tblDecimalTest (FieldDecimal) VALUES (?)')
>>     New DBI::st (for DBD::ODBC::st, parent=DBI::db=HASH(0x260a18),
> id=)
>>     dbih_setup_handle(DBI::st=HASH(0x260b20)=>DBI::st=HASH(0x1b9d48),
>> DBD::ODBC::st, 260b2c, Null!)
>>     dbih_make_com(DBI::db=HASH(0x260a18), 136f30, DBD::ODBC::st, 212, 
>> 0) thr#0
>>     dbih_setup_attrib(DBI::st=HASH(0x1b9d48), Err,
>> DBI::db=HASH(0x260a18)) SCALAR(0x1face0) (already defined)
>>     dbih_setup_attrib(DBI::st=HASH(0x1b9d48), State,
>> DBI::db=HASH(0x260a18)) SCALAR(0x1fad40) (already defined)
>>     dbih_setup_attrib(DBI::st=HASH(0x1b9d48), Errstr,
>> DBI::db=HASH(0x260a18)) SCALAR(0x1fad10) (already defined)
>>     dbih_setup_attrib(DBI::st=HASH(0x1b9d48), TraceLevel,
>> DBI::db=HASH(0x260a18)) 0 (already defined)
>>     dbih_setup_attrib(DBI::st=HASH(0x1b9d48), FetchHashKeyName,
>> DBI::db=HASH(0x260a18)) 'NAME_uc' (already defined)
>>     dbih_setup_attrib(DBI::st=HASH(0x1b9d48), HandleSetErr,
>> DBI::db=HASH(0x260a18)) undef (not defined)
>>     dbih_setup_attrib(DBI::st=HASH(0x1b9d48), HandleError,
>> DBI::db=HASH(0x260a18)) undef (not defined)
>>     initializing sth query timeout to 0
>>     ignore named placeholders = 0
>>     dbd_preparse scanned 1 distinct placeholders
>>     SQLPrepare returned 0
>> 
>>     dbd_st_prepare'd sql f2787256, ExecDirect=0
>>       INSERT INTO tblDecimalTest (FieldDecimal) VALUES (?)
>>     <- prepare= DBI::st=HASH(0x260b20) at ./insert.pl line 14
>>     >> bind_param  DISPATCH (DBI::st=HASH(0x260b20) rc1/1 @4 g0 ima1
>> pid#5169) at ./insert.pl line 16
>>     -> bind_param for DBD::ODBC::st (DBI::st=HASH(0x260b20)~0x1b9d48 1
> 
>> 10 HASH(0x1209b8)) bind 1 <== '10' (attribs: HASH(0x1209b8)), type 3
>>     <- bind_param= 1 at ./insert.pl line 16
>>     >> execute     DISPATCH (DBI::st=HASH(0x260b20) rc1/1 @1 g0
> ima1041
>> pid#5169) at ./insert.pl line 18
>>     -> execute for DBD::ODBC::st (DBI::st=HASH(0x260b20)~0x1b9d48)
>>     dbd_st_execute (outparams = 0)...
>> bind 1 <== 10 (size 2/3/0, ptype 6, otype 1, sqltype 3) bind 1 <== 
>> '10' (len 2/2, null 0)
>>     bind 1: CTy=1, STy=DECIMAL, CD=2, Sc=2, VM=2.
>>     SQLBindParameter: idx = 1: fParamType=1, name=1, fCtype=1, 
>> SQL_Type = 3, cbColDef=2, scale=2, rgbValue = 13ddc0, cbValueMax=2,
> cbValue = 2
>>     Param value = 10
>>    rebind check char Param 1 (10)
>>     dbd_st_execute (for hstmt 2787256 before)...
>>     dbd_st_execute (for hstmt 2787256 after, rc = -1)...
>> dbd_error: err_rc=-1 rc=0 s/d/e: 2787256/2497728/2496296
>> dbd_error: SQL-22003 (native 0): [unixODBC][Microsoft][ODBC SQL Server
> 
>> Driver]Numeric value out of range (SQL-22003)
>> dbd_error: err_rc=-1 rc=0 s/d/e: 0/2497728/2496296
>> dbd_error: err_rc=-1 rc=0 s/d/e: 0/0/2496296 st_execute/SQLExecute 
>> error -1 recorded: [unixODBC][Microsoft][ODBC SQL Server 
>> Driver]Numeric value out of range (SQL-22003)(DBD:
>> st_execute/SQLExecute err=-1)
>>     !! ERROR: -1 '[unixODBC][Microsoft][ODBC SQL Server Driver]Numeric
> 
>> value out of range (SQL-22003)(DBD: st_execute/SQLExecute err=-1)'
>> (err#0)
>>     <- execute= undef at ./insert.pl line 18
>>     >> DESTROY     DISPATCH (DBI::st=HASH(0x260b20) rc1/1 @1 g0 ima4
>> pid#5169)
>>     <> DESTROY(DBI::st=HASH(0x260b20)) ignored for outer handle (inner
>> DBI::st=HASH(0x1b9d48) has ref cnt 1)
>>     >> DESTROY     DISPATCH (DBI::st=HASH(0x1b9d48) rc1/1 @1 g0 ima4
>> pid#5169)
>>     -> DESTROY for DBD::ODBC::st (DBI::st=HASH(0x1b9d48)~INNER)
>>    SQLFreeStmt called, returned 0.
>>        ERROR: -1 '[unixODBC][Microsoft][ODBC SQL Server Driver]Numeric
> 
>> value out of range (SQL-22003)(DBD: st_execute/SQLExecute err=-1)'
>> (err#0)
>>     <- DESTROY= undef
>>     DESTROY (dbih_clearcom) (sth 0x260b20, com 0x2a8690, imp
>> DBD::ODBC::st):
>>        FLAGS 0x180191: COMSET Warn RaiseError PrintError PrintWarn 
>>        PARENT DBI::db=HASH(0x260a18)
>>        KIDS 0 (0 Active)
>>        IMP_DATA undef
>>        NUM_OF_FIELDS -1
>>        NUM_OF_PARAMS 1
>>     dbih_clearcom 0x260b20 (com 0x2a8690, type 3) done.
>> 
>>     -- DBI::END
>>     >> disconnect_all DISPATCH (DBI::dr=HASH(0x1fa794) rc1/4 @1 g0
>> ima801 pid#5169) at
>> /usr/perl5.8.7/lib/site_perl/5.8.7/sun4-solaris/DBI.pm line 677 via 
>> ./insert.pl line 0
>>     -> disconnect_all for DBD::ODBC::dr
>> (DBI::dr=HASH(0x1fa794)~0x25303c)
>>     <- disconnect_all= '' at
>> /usr/perl5.8.7/lib/site_perl/5.8.7/sun4-solaris/DBI.pm line 677 via 
>> ./insert.pl line 0
>> !   >> DESTROY     DISPATCH (DBI::db=HASH(0x260a18) rc1/1 @1 g0 ima4
>> pid#5169) during global destruction
>> !   -> DESTROY for DBD::ODBC::db (DBI::db=HASH(0x260a18)~INNER)
>> ** auto-rollback due to disconnect without commit returned 1
>>   DBD::ODBC Disconnected!
>>        ERROR: -1 '[unixODBC][Microsoft][ODBC SQL Server Driver]Numeric
> 
>> value out of range (SQL-22003)(DBD: st_execute/SQLExecute err=-1)'
>> (err#0)
>> !   <- DESTROY= undef during global destruction
>>     DESTROY (dbih_clearcom) (dbh 0x25300c, com 0x136f30, imp global
>> destruction):
>>        FLAGS 0x180191: COMSET Warn RaiseError PrintError PrintWarn 
>>        PARENT DBI::dr=HASH(0x25303c)
>>        KIDS 0 (0 Active)
>>        IMP_DATA undef
>>     dbih_clearcom 0x25300c (com 0x136f30, type 2) done.
>> 
>> !   >> DESTROY     DISPATCH (DBI::dr=HASH(0x25303c) rc1/1 @1 g0 ima4
>> pid#5169) during global destruction
>> !   -> DESTROY in DBD::_::common for DBD::ODBC::dr
>> (DBI::dr=HASH(0x25303c)~INNER)
>> !   <- DESTROY= undef during global destruction
>>     DESTROY (dbih_clearcom) (drh 0x1fa794, com 0x136460, imp global
>> destruction):
>>        FLAGS 0x100215: COMSET Active Warn PrintWarn AutoCommit 
>>        PARENT undef
>>        KIDS 1 (1 Active)
>>        IMP_DATA undef
>>     dbih_clearcom 0x1fa794 (com 0x136460, type 1) done.
>> 
>> !   >> DESTROY     DISPATCH (DBI::dr=HASH(0x1fa794) rc1/1 @1 g0 ima4
>> pid#5169) during global destruction
>> !   <> DESTROY for DBI::dr=HASH(0x1fa794) ignored (inner handle gone)
>> !   >> DESTROY     DISPATCH (DBI::db=HASH(0x25300c) rc1/1 @1 g0 ima4
>> pid#5169) during global destruction
>> !   <> DESTROY for DBI::db=HASH(0x25300c) ignored (inner handle gone)
>> 
>> 
>> 

Reply via email to