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

Maybe someone can help me out here. I am running IIS5 and SQL 2000 Server (both on my laptop for testing purposses, will be changed to my IIS Server and SQL server later) the code below will allow me to do the search, update and delete so I know that I am connecting to SQL 2000 but the INSERT statement will not work. I'v tried making changes to no avail. I can hardwire the INSERT statement and run it from the command line and it works. Anybody have any ideas as to what I am doing wron here?
#! /usr/bin/perl -w # todo5.pl - like todo4.pl, but: # - adds search capability for items use strict; use lib qw(/usr/local/apache/lib/perl); use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use WebDB; #@ MAIN_LOGIC print header (), start_html (-title => "To-Do List", -bgcolor => "white"), h2 ("To-Do List"); my $dbh = WebDB::connect (); # Dispatch to proper action based on user selection my $choice = lc (param ("choice")); # get choice, lowercased if ($choice eq "") # initial sc +ript invocation { display_entry_form (); display_current_items ($dbh); } elsif ($choice eq "submit") { insert_item ($dbh, param ("content")); display_entry_form (); display_current_items ($dbh); } #@ MAIN_DELETE_CLAUSE elsif ($choice eq "delete") { if (!delete_item ($dbh, param ("id"))) { print p ("No record with id " . param ("id") . " was f +ound"); } display_entry_form (); display_current_items ($dbh); } #@ MAIN_DELETE_CLAUSE #@ MAIN_EDIT_CLAUSE elsif ($choice eq "edit") { if (my $row = select_item ($dbh, param ("id"))) { display_edit_form ($row); } else { print p ("No record with id " . param ("id") . " was f +ound"); display_current_items ($dbh); } } elsif ($choice eq "update") { update_item ($dbh, param ("id"), param ("content"), param ("st +atus")); display_entry_form (); display_current_items ($dbh); } elsif ($choice eq "cancel") { display_entry_form (); display_current_items ($dbh); } #@ MAIN_EDIT_CLAUSE #@ MAIN_SEARCH_CLAUSE elsif ($choice eq "search") { display_entry_form (); display_search_hits ($dbh, param ("content")); } #@ MAIN_SEARCH_CLAUSE else { print p ("Logic error, unknown choice: $choice"); } $dbh->disconnect (); print end_html (); #@ MAIN_LOGIC exit (0); # -------------------------------------------------------------------- +-- # Insert new to-do item if the content is non-empty. #@ INSERT_ITEM sub insert_item { my ($dbh, $t, $content); $t =~ s/^\s+//; # strip leading whitespace $t =~ s/\s+$//; # strip trailing whitespace $content =~ s/^\s+//; # strip leading whitespace $content =~ s/\s+$//; # strip trailing whitespace if ($content ne "") # if content is non-empty, +add to table { $dbh->do (qq{ INSERT INTO todo SET date = ?, status = " +open", content = ? }, undef, $t, $content); } } #@ INSERT_ITEM #@ SELECT_ITEM sub select_item { my ($dbh, $id) = @_; my ($sth, $row); $sth = $dbh->prepare (qq{ SELECT * FROM todo WHERE id = ? }); $sth->execute ($id); $row = $sth->fetchrow_hashref (); $sth->finish (); return ($row); } #@ SELECT_ITEM # Update an item and return the row count (0 if item wasn't found or c +hanged) #@ UPDATE_ITEM sub update_item { my ($dbh, $id, $content, $status) = @_; $content =~ s/^\s+//; # strip whitespace $content =~ s/\s+$//; $dbh->do (qq{ UPDATE todo SET content = ?, status = ? WHERE id + = ? }, undef, $content, $status, $id); } #@ UPDATE_ITEM # Delete an item and return the row count (0 if item wasn't found) #@ DELETE_ITEM sub delete_item { my ($dbh, $id) = @_; return ($dbh->do (qq{ DELETE FROM todo WHERE id = ? }, undef, $id)); } #@ DELETE_ITEM # Display entry form #@ DISPLAY_ENTRY_FORM sub display_entry_form { print strong ("Item Entry Form"), start_form (-action => url ()), "Date:", br (), textarea (-name => "date", -value => "", -override => 1, -rows => 1, -columns => 15), br (), "Things To Do:", br (), textarea (-name => "content", -value => "", -override => 1, -rows => 3, -columns => 80), br (), #@ SEARCH_MOD_AFTER #@ SEARCH_MOD_BEFORE submit (-name => "choice", -value => "Submit"), #@ SEARCH_MOD_BEFORE submit (-name => "choice", -value => "Search"), #@ SEARCH_MOD_AFTER end_form (); } #@ DISPLAY_ENTRY_FORM # Display form for editing item $id. The content text field and statu +s # radio buttons are set to their current values. The id is placed in +the # form as a hidden field so it is transmitted back to the server when # the form is submitted. #@ DISPLAY_EDIT_FORM sub display_edit_form { my $row = shift; print strong ("Item Editing Form"), start_form (-action => url ()), "Date:", br (), textarea (-name => "date", -value => "", -override => 1, -rows => 1, -columns => 15), br (), "Things To Do:", br (), textarea (-name => "content", -value => "", -override => 1, -rows => 3, -columns => 80), br (), radio_group (-name => "status", -values => ["open", "closed", +"in-progress"], -default => $row->{status}), br (), submit (-name => "choice", -value => "Update"), submit (-name => "choice", -value => "Cancel"), end_form (); } #@ DISPLAY_EDIT_FORM # If there are any entries, display them, most recent entries first.. #@ DISPLAY_CURRENT_ITEMS sub display_current_items { my $dbh = shift; my ($sth, $stmt, $count); print hr (), strong ("Current items:"); $stmt = qq { SELECT * FROM todo ORDER BY date DESC }; $sth = $dbh->prepare ($stmt); $sth->execute (); $count = 0; while (my $row = $sth->fetchrow_hashref ()) { display_item ($row); ++$count; } $sth->finish (); print p ("No items were found") if $count == 0; } #@ DISPLAY_CURRENT_ITEMS # Look for the given string in existing items and display them #@ DISPLAY_SEARCH_HITS sub display_search_hits { my ($dbh, $str) = @_; my ($sth, $stmt, $count); print hr (), p ("Search Results"); $str =~ s/^\s+//; # strip whitespace $str =~ s/\s+$//; if ($str eq "") # cancel search if there's noth +ing to search for { print p ("No search term was entered"); return; } print hr (), strong ("Items matching \"$str\":"); $stmt = qq { SELECT * FROM todo WHERE content LIKE ? ORDER BY +date DESC }; $sth = $dbh->prepare ($stmt); $sth->execute ("%$str%"); # search for wildcard form of string $count = 0; while (my $row = $sth->fetchrow_hashref ()) { display_item ($row); ++$count; } $sth->finish (); print p ("No matching items were found") if $count == 0; } #@ DISPLAY_SEARCH_HITS #@ DISPLAY_ITEM sub display_item { my $row = shift; my ($edit_url, $delete_url); $edit_url = sprintf ("%s?choice=edit;id=%d", url (), $row->{id +}); $delete_url = sprintf ("%s?choice=delete;id=%d", url (), $row- +>{id}); print br (), br (), "$row->{t} $row->{status}", " [", a ({-href => $edit_url}, "Edit"), "]", " [", a ({-href => $delete_url}, "Delete"), "] +", br (), "\n", "$row->{content}\n"; } #@ DISPLAY_ITEM
or this type of INSERT with a {my @field_list} set up
sub insert_record { my $field_ref = shift; # reference to field list my $dbh; my $stmt; my @placeholder; my $rows; $dbh = WebDB::connect (); $stmt = ""; @placeholder = (); foreach my $f (@{$field_ref}) { next if $f->{value} eq ""; # don't both +er with empty fields $stmt .= "," if $stmt; # put co +mmas between assignments $stmt .= $f->{name} . " = ?"; # add column name +, placeholder push (@placeholder, $f->{value}); # save placeh +older value } $stmt = "INSERT INTO prodreg SET $stmt"; # complete the + statement #@ INSERT_RECORD_CHECK_RESULT $rows = $dbh->do ($stmt, undef, @placeholder); #@ INSERT_RECORD_CHECK_RESULT $dbh->disconnect (); # display confirmation to customer
This second INSERT gives me this error in the browser:

DBD::ODBC::db do failed: MicrosoftODBC SQL Server DriverSQL ServerIncorrect syntax near the keyword 'SET'. (SQL-42000) MicrosoftODBC SQL Server DriverSQL ServerStatement(s) could not be prepared. (SQL-42000)(DBD: st_execute/SQLExecute err=-1) at d:\public\default\scripts\prod_reg.pl line 297.

Edit by tye, add READMORE

Replies are listed 'Best First'.
Re: INSERT into SQL 2000
by runrig (Abbot) on Jul 14, 2003 at 21:34 UTC
    I don't know if SQL Server is any different, but I'm not aware that there is any 'SET' keyword in an INSERT statement. The usual syntax is:
    insert into table_name (column_name1, column_name2) values (value1, value2)
    I almost didn't even bother reading your post. Was it really necessary to post over 300 lines of code to demonstrate an insert statement that doesn't work?
      I think you're correct about INSERT. Usually the SET keyword is used with an UPDATE statement, IIRC. The inquiring monk did say that it worked from a command line, though.
Re: INSERT into SQL 2000
by WhiteBird (Hermit) on Jul 14, 2003 at 21:32 UTC
    Given the error message "Incorrect syntax near the keyword 'SET'" , I would speculate that you have a SQL server error. Are you absolutely sure that your SQL statement is correct? You might want to drop a print statement in your code to have the SQL print out prior to the prepare so that you can see if it is being passed on correctly.
      I will have to agree with the rest. I programmed SQL for about a year, and I never once used the SET command with INSERT. It should be like this:
      INSERT INTO myTable myColumn1, myColumn2, ...
      I removed the SET and tried to change the INSERT statement to a standard INSERT statement. It doesn't work then either. The carp doesn't show me any errors. The script does operates the way it is supposed to but will not post to the table.
Re: INSERT into SQL 2000
by gellyfish (Monsignor) on Jul 15, 2003 at 11:28 UTC

    I might be going blind here but it appears that you are using a new lexical $dbh in your insert_record() subroutine. I am surprised it doesn't croak with an error though.

    /J\
    
Re: INSERT into SQL 2000
by poj (Abbot) on Jul 15, 2003 at 18:42 UTC
    Paul DuBois uses MySQL where INSERT INTO tablename SET fieldname=value is allowed, I'm not sure this is so for SQL 2000.
    However, in the first case, you are calling the sub with 2 parameters here
    insert_item ($dbh, param ("content"));
    but the sub is written for 3, although none are initialised. I think your mistake is here
    # my ($dbh, $t, $content); NOT THIS my ($dbh, $t, $content) = @_; #
    In the second piece of code, I would temporarily change this line as follows, and display $rows in the page
    #$rows = $dbh->do ($stmt, undef, @placeholder); $rows = qq[ dbh->do ($stmt, undef, @placeholder) ];
    If all the values are "" then $stmt would be INSERT INTO prodreg SET which would be invalid.
    poj
      Thing is, even if its valid, it shouldn't be needed for SQL. You should just be able to put INSERT INTO Tablename value, value, value, ....