Kanishka has asked for the wisdom of the Perl Monks concerning the following question:

The script below give this Error!
DBD::ODBC::st execute failed: MicrosoftODBC SQL Server DriverInvalid character value for cast specification (SQL-22018)(DBD: st_execute/SQLExecute err=-1)
use LWP::Simple; use HTML::TableExtract; use DBI; my $dbh1 = DBI->connect('DBI:ODBC:OptionsDB', 'sa', '') or die "Couldn +'t connect to database: " . DBI->errstr; my $sth1 = $dbh1->prepare('INSERT INTO OptionsDB..MyOpt (Security, Vol +ume, Previous, TodayHigh, TodayLow, TodayClose, Change) VALUES (?,?,? +,?,?,?,?)') or die "Couldn't prepare statement: " . $dbh1->errstr; use Data::Dumper; open (CSEFILE, 'SCE.htm'); $/ = undef; my $response = <CSEFILE>; $/ ="\n"; close CSEFILE; $response =~ s/.*Statistics//s; $response =~ s/Volume Weighted Average.*//s; $response =~ s/[\r\n]//gs; $response =~ s/\t+/ /gs; $response =~ s/ +/ /gs; #my $te = HTML::TableExtract->new( headers => ['Time', 'Security', 'Vo +lume', 'Previous', 'High', 'Low', 'Today\'s', 'Change'] ); my $te = HTML::TableExtract->new( headers => ['Security', 'Volume', 'P +revious', 'High', 'Low', 'Today\'s', 'Change'] ); #my $content = get("http://www.cse.lk/marketinfo/splsum.jsp"); $te->parse($response); foreach $ts ($te->table_states) { foreach $row ($ts->rows) { #print Dumper $row; #print @{$row},"\n"; #print $row->[0]."\t".$row->[1]."\t".$row->[2]."\t".$row->[3]. +"\t".$row->[4]."\t".$row->[5]."\t".$row->[6]."\t".$row->[7]."\n"; $Security = $row->[0]; $Volume = $row->[1]; $Previous = $row->[2]; $TodayHigh = $row->[3]; $TodayLow = $row->[4]; $TodayClose = $row->[5]; $Change = $row->[6]; print $row->[0]."\t".$row->[1]."\t".$row->[2]."\t".$row->[3]." +\t".$row->[4]."\t".$row->[5]."\t".$row->[6]."\n"; #$sth1->execute($row->[0], $row->[1], $row->[2], $row->[3], $r +ow->[4], $row->[5], $row->[6]) or die "Couldn't execute statement: " +. $sth1->errstr; $sth1->execute($Security, $Volume, $Previous, $TodayHigh, $Tod +ayLow, $TodayClose, $Change) or die "Couldn't execute statement: " . +$sth1->errstr; } }
SCE.htm is at http://www.cse.lk/marketinfo/splsum.jsp
I Use MSSQL server 2000 on a w2k environment.

1. I need a solution to the SQL error.
2. Is there any way that i could rewrite this code shorter?

Replies are listed 'Best First'.
Re: Invalid character value for cast specification
by tlm (Prior) on Apr 21, 2005 at 04:43 UTC

    It looks to me like you have one dot too many in OptionsDB..MyOpt .

    Anyway, FWIW, here's a slightly shortened version of your script.

    use strict; use warnings; use HTML::TableExtract; use DBI; my $dbh1 = DBI->connect('DBI:ODBC:OptionsDB', 'sa', '') or die "Couldn't connect to database: " . DBI->errstr; my $sth1 = $dbh1->prepare(<<'EOSQL') INSERT INTO OptionsDB.MyOpt (Security, Volume, Previous, TodayHigh, TodayLow, TodayClose, Change +) VALUES (?,?,?,?,?,?,?) EOSQL or die "Couldn't prepare statement: " . $dbh1->errstr; open CSEFILE, 'SCE.htm' or die "Failed to read SCE.htm\n"; my $response = do { local $/; <CSEFILE> }; close CSEFILE; # Do you need the following s///'s transformations if you are going to # have HTML::TableExtract parse $response ??? $response =~ s/.*Statistics//s; $response =~ s/Volume Weighted Average.*//s; $response =~ s/[\r\n]//gs; $response =~ s/[ \t]+/ /gs; my $te = HTML::TableExtract->new( headers => qw( Security Volume Previous High Low Today's Change ) ); $te->parse( $response ); for my $ts ( $te->table_states ) { for my $row ( $ts->rows ) { print join( "\t", @$row ), "\n"; $sth1->execute( @$row ) or die "Couldn't execute statement: " . $sth1->errstr; } }

    the lowliest monk

      Slightly shorter still...
      for my $ts (HTML::TableExtract->new(headers=>qw(Security Volume Previo +us High Low Today's Change)) ->parse($response)->table_states ) { for my $row ( $ts->rows ) { print join("\t", @$row), "\n"; $sth1->execute( @$row ) or die "Couldn't execute statement: " . $sth1->errstr; } }

      Presuming that the s/// transformations may be unnecessary as tlm pointed out:

      open CSEFILE, 'SCE.htm' or die "Failed to read SCE.htm\n"; for my $ts (HTML::TableExtract->new(headers => qw(Security Volume Prev +ious High Low Today's Change)) ->parse(do { local $/; <CSEFILE> })->table_states) { for my $row ( $ts->rows ) { print join("\t", @$row), "\n"; $sth1->execute( @$row ) or die "Couldn't execute statement: " . $sth1->errstr; } } close CSEFILE;

      As to whether there are more efficent ways to do this, given the context you may be interested in the Finance modules.

Re: Invalid character value for cast specification
by imp (Priest) on Aug 30, 2006 at 19:54 UTC
    I encountered this error today using DBI to update a SQL Server 2000 database using DBD::ODBC.

    The problem code is as follows:

    my $sql = q{select * from accountaction where action_date > ?}; my $sth = $dbh->prepare($sql); $sth->execute('01-01-2006'); $sth->finish;
    The same code, but without the bound parameter worked correctly:
    my $sql = q{select * from accountaction where action_date > '01-01 +-2006'}; my $sth = $dbh->prepare($sql); $sth->execute(); $sth->finish;
    The issue was that DBD::ODBC did not like the MM-DD-YYYY date format.
    Changing it to the following fixed the error for me:
    my $sql = q{select * from accountaction where action_date > ?}; my $sth = $dbh->prepare($sql); $sth->execute('2006-01-01'); $sth->finish;
    This likely occurs because SQL Server can have different date formats, e.g. DD-MM-YYYY for some locales. So to be safe it only allow the YYYY-MM-DD format.

    This response is being added to a somewhat old node because it is the only relevant one I found using Super Search, and I would like to save future searchers some trouble.

      Huge thanks- you did in fact "save future searchers some trouble", big time!

      I was getting this error too, and I didn't realize it was because I hadn't included the hyphens in the date. I'm so used to doing '20130325' in SQL Server, and it does accept that form in other contexts.

      But for parameterized queries, apparently one needs the hyphens like "2013-03-25', because once I read your comment and put the hyphens in, problem solved.

      (Yes I love replying to a post 7 years after it was written, just to say thanks to a guy who will probably never read this)

Re: Invalid character value for cast specification
by jbrugger (Parson) on Apr 21, 2005 at 04:47 UTC
    i'm wondering...
    1. I don't understand this part of the sql statement: OptionsDB..MyOpt (the .. and MyOpt).
    You mean DBName.Table?
    Update ok, then tlm is right: your query has a period to much.

    2. Well, start using strict and warnings. You see a lot undeclared variables (but some you have declared?)
    What is the use of $Change = $row->[6]; when in the next line you print print $row->[6] in stead of print $change?
    Later in the execute statement you use $change again...
    I think it will be shorter just by cleaning up.

    And have a look at your regexp... when using .* it's better to not be greedy.

    "We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise." - Larry Wall.
      OptionsDB..MyOpt
      OptionsDB is the Datebase
      MyOpt is the table