Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Perl DBI query of MS SQL with LIKE

by gcasa (Novice)
on May 29, 2023 at 09:15 UTC ( [id://11152453]=perlquestion: print w/replies, xml ) Need Help??

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

Good Day and Thank You for taking the time to share your wisdom!

I have searched for an answer to my question to no avail.

My dilemma:
When attempting to execute a query against an MS SQL server, it returns undef. When I execute the query from a cmd prompt, it returns a row. This is Strawberry Perl on a Windows machine.

The query does not seem to use the % in the LIKE no matter how I phrase it. Are there other options? Am I missing something?

My code:

## Prepare the Select Handle for the Transaction Code in the Descripti +on field my $select_TransactionCode_handle = $db_handle->prepare( qq{ SELECT [Code] FROM [Transaction Code] WHERE [Description] LIKE ? } ); $select_TransactionCode_handle->execute( $transactionCodeQuery . '%' ) +; # THIS DID NOT WORK # $select_TransactionCode_handle->bind_param( 1, $transactionCodeQuery + . '%' ); # THIS ALSO DID NOT WORK # $select_TransactionCode_handle->execute; # $select_TransactionCode_handle->bind_param( 1, $transactionCodeQuery + ); # THIS ALSO DID NOT WORK # $select_TransactionCode_handle->execute( '%' ); ## Grab the Transaction Code if it already exists my @transactionCodes = $select_TransactionCode_handle->fetchrow_array; + # THIS RETURNS undef

The information returned includes this: "$select_TransactionCode_handle->{$transactionCodeQuery.'*'} = undef;". I do not know where the '*' is coming from.

I am hoping I have missed something simple. :-)

Thank You in Advance! Please let me know if you need more information! Thanks for your time!

glenn

Replies are listed 'Best First'.
Re: Perl DBI query of MS SQL with LIKE
by Corion (Patriarch) on May 29, 2023 at 09:45 UTC

    How did you verify that $transactionCodeQuery contains exactly what you think it should? Does it contain whitespace?

      In addition to verifying before you call, using the DBI trace method to watch what actually is passed to the DB can help.

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        Thank You for your sharing your wisdom!

        Corion, Yes the query contains spaces and even a #. I had only verified $transactionCodeQuery by printing it to STDOUT. At 2am I was not comprehending how to TRACE.

        Fletch, I have just learned how to use TRACE and added it to my statement handle.
        Trace Output at level 5: DBI::st=HASH(0x4a7dff0) trace level set to 0x0/5 (DBI @ 0x0/0) in +DBI 1.643-ithread (pid 16980) -> execute for DBD::ODBC::st (DBI::st=HASH(0x4a7e038)~0x4a7dff0 'N +DC #29300-0415-10%') thr#f66fe8 +dbd_bind_ph(4a7ded0, name=1, value='NDC #29300-0415-10%', attribs +=, sql_type=0(unknown), is_inout=0, maxlen=0 First bind of this placeholder -dbd_bind_ph=rebind_param +rebind_param 1 'NDC #29300-0415-10%' (size SvCUR=19/SvLEN=21/max= +0) svtype:3, value type:1, sql type:0 +get_param_type(4a7ded0,1) SQLDescribeParam 1: SqlType=VARCHAR(12) param_size=40 Scale=0 Nu +llable=0 check_for_unicode_param - sql_type=unknown, described=VARCHAR bind 1 'NDC #29300-041...' value_len=19 maxlen=19 null=0) bind 1 value_type:1 VARCHAR cs=40 dd=0 bl=19 SQLBindParameter: idx=1: io_type=1, name=1, value_type=1 (SQL_C_CH +AR), SQLType=12 (VARCHAR), column_size=40, d_digits=0, value_ptr=48ae +598, buffer_length=19, ind=19, param_size=40 Param value = NDC #29300-0415-10% -rebind_param +dbd_st_execute_iv(4a7ded0) dbd_st_finish(4a7ded0) outparams = 0 SQLNumResultCols=0 (flds=1) dbd_describe done_desc=0 dbd_describe SQLNumResultCols=0 (columns=1) now using col 1: type = UNICODE VARCHAR (-9), len = 20, display s +ize = 20, prec = 9, scale = 0 -dbd_describe done_bind=0 have 1 fields -dbd_st_execute_iv(4a7ded0)=0 <- execute= ( '0E0' ) [1 items] at C:\PrimeRxToLytec\bin\PrimeRxTo +Lytec.pl line 814 -> fetchrow_array for DBD::ODBC::st (DBI::st=HASH(0x4a7e038)~0x4a7 +dff0) thr#f66fe8 bind_columns fbh=3d55af8 fields=1 Bind 1: type = UNICODE CHAR(-8), buf=48ad8d8, buflen=20 bind_columns=0 SQLFetch=100 dbd_st_finish(4a7ded0) <- fetchrow_array= ( ) [0 items] at C:\PrimeRxToLytec\bin\PrimeRxT +oLytec.pl line 817 -> finish for DBD::ODBC::st (DBI::st=HASH(0x4a7e038)~0x4a7dff0) th +r#f66fe8 <- finish= ( 1 ) [1 items] at C:\PrimeRxToLytec\bin\PrimeRxToLytec +.pl line 838 -> DESTROY for DBD::ODBC::st (DBI::st=HASH(0x4a7dff0)~INNER) thr#f +66fe8 <- DESTROY= ( undef ) [1 items] at C:\PrimeRxToLytec\bin\PrimeRxTo +Lytec.pl line 1254 via at C:\PrimeRxToLytec\bin\PrimeRxToLytec.pl li +ne 1254
        Thank You Again for the assistance!!!

        glenn
Re: Perl DBI query of MS SQL with LIKE
by Bod (Parson) on May 29, 2023 at 18:28 UTC

    I think I would start by broadening the LIKE match...

    $select_TransactionCode_handle->execute( '%' . $transactionCodeQuery . + '% );

    I would also check exactly what $transactionCodeQuery contains.

    print "->$transactionCodeQuery<-";

    Then try the query manually at the database to ensure it is not something bizarre in the data that is giving spurious results.

    I don't use SQL Server, but for MySQL and MariaDB the syntax you are using is correct.

Re: Perl DBI query of MS SQL with LIKE
by afoken (Chancellor) on May 30, 2023 at 16:36 UTC

    Just a note on WHERE column LIKE 'something%', if this is really what you want:

    Using LIKE with only a trailing % is usually slower than using SUBSTR, or at least it was WAY slower the last time I had to do serious work with relational databases. It boils down to the query optimizer not being able to use indices on the queried column with LIKE, resulting in a full table scan. If you use SUBSTR instead, your query can be optimized to use indices and thus does not have to scan the entire table.

    So, unless SQL query optimizers have become much smarter than they were a few years ago, WHERE SUBSTR(column, 1, 9) = 'something' should be faster.


    Using DBI, there are basically three ways to pass the length of the search term to SUBSTR:

    If you can use numbered or named placeholders (depends on your database driver), you simply reuse the placeholder:

    # numbered: my $sth=$dbh->prepare('SELECT ... FROM ... WHERE SUBSTR(column, 1, LEN +GTH(:1)) = :1'); $sth->bind_param(1, $what); $sth->execute(); # named: my $sth=$dbh->prepare('SELECT ... FROM ... WHERE SUBSTR(column, 1, LEN +GTH(:what)) = :what'); $sth->bind_param(':what', $what); $sth->execute();

    If you are limited to simple ? placeholders, you can pass the same value twice:

    my $sth=$dbh->prepare('SELECT ... FROM ... WHERE SUBSTR(column, 1, LENGTH(?)) = ?'); $sth->bind_param(1, $what); $sth->bind_param(2, $what); $sth->execute(); # or without explicit bind_param: $sth->execute($what, $what); </c>

    You could also calculate the length in perl. This should normally work, unless your data contains Unicode AND perl, DBI, DBD, and the database don't agree on how your data is really encoded (i.e. you messed up the Unicode handling):

    my $sth=$dbh->prepare('SELECT ... FROM ... WHERE SUBSTR(column, 1, ?) += ?'); $sth->execute(length($what), $what);

    Note: This will cause interesting results if Unicode handling is messed up ...


    Oh, by the way: What happens if $transactionCodeQuery contains a %? If you can guarantee it does not and will never, don't mind. If $transactionCodeQuery is user input, try harder to avoid using LIKE. If there is no way around LIKE, try using ... LIKE ... ESCAPE ....

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      Using LIKE with only a trailing % is usually slower than using SUBSTR

      I cannot speak for SQL Server but with MariaDB LIKE is optimised to use indexes as long as the first character is not a wildcard - '%' or '_'

      See documentation

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11152453]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2024-04-23 15:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found