On Thu, 26 Dec 2002 12:39:53 -0500 "Rozengurtel, Daniel" 
<[EMAIL PROTECTED]> wrote:

> I have a little problem when I bound three variables from bind_param.

Be sure to make the distinction between placeholders/bind variables and
result columns.  You have two placeholders in your SELECT and it returns
three columns.

> I am using union in my sql. I am not sure where the problem comes arises.
> The three fields from each table have different names although defined and
> contain the same data (CHAR(10),VARCHAR2(40),CHAR(8)) I have
> TYPE=>SQL_CHAR.
> Do I need to define separately for each variable I bind the value to its
> type? If so how do I do that? If this is not the case, why not all of the
> vars are getting bound?

By default, each placeholder is separate from the other.  You will note in
the trace() output that you have two bind variables (:p1 and :p2).

> I include a trace from the run and a piece of code. 
> Thanx a lot in advance for your help.
> 
> CODE:
> 
> #************************************************************************
> ***
> ****
> #         prepared sqls
> #************************************************************************
> ***
> ****
> my $sth_isid_frip = 
>         $dbh->prepare(q{SELECT INST_MNEM,ID_CTXT_TYP,ISS_ID 
>                                          FROM FT_T_ISID WHERE INSTR_ID=? AND
> END_TMS IS NULL 
>                                         UNION 
>                                         SELECT
> INST_MNEM,PREF_ID_CTXT_TYP,ISID_ISS_ID FROM FT_T_FRIP WHERE INSTR_ID=? 
>                                          AND END_TMS IS NULL AND INST_MNEM
> IS NOT NULL
>                                          ORDER BY INST_MNEM,ID_CTXT_TYP}) ||
> die $dbh->errstr;

An alternative to anonymous placeholders here would be to use bind
variables.  DBD::Oracle allows either ? or :name formed
placeholders/bind variables.  In this case it would probably be easiest to
replace the '?'s with ':p1' in both places without the quotes.  That way
you can provide the value either with $sth->bind_param() or as a single
argument to $sth->execute().  If you retain the ?s, either call
$sth->bind_param() twice with 1 and 2 as the first argument or call
'$sth->execute( $val1, $val2 ) or die "Execute failed: $DBI::errstr"'.

> #************************************************************************
> ***
> ***
> 
> my ($sql, %ids_hash, $instr_id);
> 
> $instr_id='0001x5MWFg';
> 
> #****************************************************************
> # Creating a hash of ISID/FRIP ids 
> #****************************************************************
>   
>   $sth_isid_frip->bind_param(1, $instr_id, {TYPE=>SQL_CHAR});  #
> placeholders are numbered from 1

The placeholders are numbered 1 and 2, so if you are going to use
bind_param(), you need to provide both.

>   $sth_isid_frip->execute;

I don't see any error checking on the execute().  Either set
$dbh->{RaiseError} to 1 before the prepare(), or include 'or die
"Something: $DBI::errstr"' with each call.

> ## the problem is somewhere here.
> my( $prim_exch, $ctxt_typ, $id_value );
>   $sth_isid_frip->bind_columns( undef, \$prim_exch, \$ctxt_typ,
> \$id_value
> );

The first, hash reference argument is optional and probably best left out.
The \ operator is also distributive.

  $sth_isid_frip->bind_columns( \( $prim_exch, $ctxt_typ,
     $id_value ) );

I don't normally explicitly check for errors on bind_columns() because I
should have caught statement parsing errors either in prepare() or
execute().  I also usually have $dbh->{RaiseError} set.

> #process further
>   while( $sth_isid_frip->fetch() ) {
>           if (defined $prim_exch and defined $id_value and defined
> $ctxt_typ)
>                   { $ids_hash{$instr_id}{$prim_exch}{$ctxt_typ}=$id_value; }
> } #while
> 
> $sth_isid_frip->finish();

Since you are fetching all rows in the while loop, finish() is not
required and is discouraged.

> TRACE:
> 
> DBI::db=HASH(0x116be8) trace level set to 2 in DBI 1.15-nothread
>     -> prepare for DBD::Oracle::db (DBI::db=HASH(0x27ef08)~0x116be8
> 'SELECT
> INST_MNEM,ID_CTXT_TYP,ISS_ID
>                                          FROM FT_T_ISID WHERE INSTR_ID=?
> AND
> END_TMS IS NULL
>                                         UNION
>                                         SELECT
> INST_MNEM,PREF_ID_CTXT_TYP,ISID_ISS_ID FROM FT_T_FRIP WHERE INST
> R_ID=?
>                                          AND END_TMS IS NULL AND
> INST_MNEM
> IS NOT NULL
>                                          ORDER BY INST_MNEM,ID_CTXT_TYP')
>     dbd_preparse scanned 2 distinct placeholders

Note the number of distinct placeholders.

>     fbh 1: 'INST_MNEM'  NULLable, otype  96->  5, dbsize 8/9, p8.s0
>     fbh 2: 'ID_CTXT_TYP'        NULLable, otype  96->  5, dbsize 8/9,
> p8.s0
>     fbh 3: 'ISS_ID'     NULLable, otype   1->  5, dbsize 40/41, p40.s0

And the three separate returned fields.

>     <- prepare= DBI::st=HASH(0x26fb94) at get_isid_frip_ids.pl line 88.
>     -> bind_param for DBD::Oracle::st (DBI::st=HASH(0x26fb94)~0x1079cc 1
> '0001x5MWFg' HASH(0x117a8c))
>        bind :p1 <== '0001x5MWFg' (type 1, attribs: HASH(0x117a8c))
>        bind :p1 <== '0001x5MWFg' (size 10/11/0, ptype 4, otype 96)
>     <- bind_param= 1 at get_isid_frip_ids.pl line 106.

Note that DBD::Oracle renamed the placeholder as bind variable :p1.  There
is also a :p2 that you did not given a value for ...

>     -> execute for DBD::Oracle::st (DBI::st=HASH(0x26fb94)~0x1079cc)
>     dbd_st_execute SELECT (out0, lob0)...
>     !! ERROR: 1008 'ORA-01008: not all variables bound (DBD ERROR:
> OCIStmtExecute)'

as this tells you.  That error message is available in $DBI::errstr or
$sth_isid_frp->errstr, so trace()ing wasn't necessary to see it.

>     <- execute= undef at get_isid_frip_ids.pl line 107.

-- 
Mac :})
** I normally forward private questions to the appropriate mail list. **
Ask Smarter: http://www.tuxedo.org/~esr/faqs/smart-questions.html
Give a hobbit a fish and he eats fish for a day.
Give a hobbit a ring and he eats fish for an age.


Reply via email to