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

I have a situation where I'm looping through to generate a SQL statement to update a table. Wha'ts happening though is The site name has an apostrophe in the value and the perl script throws an error at that point.

SQL = UPDATE LIR_BUT_SITE SET ROW_IDENTIFIER = '4' , M_CUSTOMER_ABBREV = 'IBHW' , M_SITE_KEY = 'R_LIR_BUT_SITE-' , RESP_CENTER = 'Global Custom Svcs GCSC' , M_SITE_NAME = 'MZ3481-CHILDREN'S HOSPITAL WALTHAM'
Here is the piece of code that generates the SQL
for $idx (0..$#hdr) { if ($row[$idx] ne "") { if ($found ne "N") { $updstmt .= ", "; $insstmt .= ", "; $valstmt .= ", "; } $found = "Y"; $updstmt .= $hdr[$idx]." = '".$row[$idx]."' \ +r\n";

The values for the update are generated by the $row$idx.How do I put that $row$idx within double quotes or how do i make the perl interpreter escape any apostrophes in that field. Can some one suggest a solution?

Thanks.

Replies are listed 'Best First'.
Re: Escaping Apostrophe
by haukex (Archbishop) on Oct 20, 2017 at 13:49 UTC

    My first suggestion is to not re-invent the wheel, see for example SQL::Abstract (Update: example).

    Also, you should always use placeholders wherever possible - see Bobby Tables!

    DBI provides quote and quote_identifier, but I'd consider those a last resort if the above is not applicable for whatever unlikely reason.

      Not trying to reinvent the wheel. But this is the code we have in just one of many places, using abstract or anything else will require a lot of changes through the code. All I need is a quick and dirty solution with what I have.

        Quick, dirty — and, per other replies, kinda crazy (and also untested):

        my ($row_sub_i_esc_sq = $row[$idx]) =~ s{ ' }{\\}xmsg; $updstmt .= $hdr[$idx]." = '". $row_sub_i_esc_sq ."' \r\n";
        And BTW: It looks like you're dealing with single-quote characters, not apostrophes.

        Update: Oops... Meant to write  s{ (?= ') }{\\}xmsg; and the substitute-on-assignment expression is also wrong, so finally (I think):

        (my $row_sub_i_esc_sq = $row[$idx]) =~ s{ (?= ') }{\\}xmsg; $updstmt .= $hdr[$idx]." = '". $row_sub_i_esc_sq ."' \r\n";
        Thanks choroba. Of course, that's what always happens when I post untested stuff.


        Give a man a fish:  <%-{-{-{-<

Re: Escaping Apostrophe
by Your Mother (Archbishop) on Oct 20, 2017 at 15:35 UTC

    DBI->quote is probably what you want. I agree with the comments already made however that eschewing placeholders is madness and any DB code that works without them, or quote at least, is insecure and depending on the data pipeline, very risky.

Re: Escaping Apostrophe
by LanX (Saint) on Oct 20, 2017 at 14:31 UTC
Re: Escaping Apostrophe
by Your Mother (Archbishop) on Oct 21, 2017 at 02:59 UTC

    Follow up story. I inherited a code base—for a financial website no less—with scads of string building SQL handling like this. It was a dangerously insecure mess. I wanted to refactor, rather than extend and muddy it even more, with DBIx::Class but it wasn't installed and as a contractor, I couldn't do it or even get a request answered. I noticed that SQL::Abstract was already there. But then I had the same, fairly wise, hesitancy you do. I was almost guaranteed to break a money making app and maybe get my contract cancelled if I started attempting to introduce better practices at the expense of a working app.

    So, I started finishing the tests I'd been writing focusing on testing the SQL generating routines. When I had complete coverage, which did not take long, I started to refactor with SQL::Abstract. A couple days later it was all done. I did indeed break several things at first and misunderstood a few parts so my new code was wrong but the tests told me my mistakes. It went into production a week or so after I started without any problems at all.