Mysqli Update Prepare Failing - php

if ($stmt = $mysqli->prepare("UPDATE profile SET fullname =?, guardian =?,
addressline1 = ?, addressline2 = ?, city = ?, stateid = ?, pin = ?, birthdate = ?,
bloodgroup= ?, allergydetails= ?, pancardno= ?, officephone= ?, residencephone= ?,
mobilephone= ?, drivinglicensenumber= ?, drivinglicensevalidupto= ?,
fmscidrivinglicensenumber= ?, fmscientrantlicensenumber= ?, vehiclemake= ?,
vehiclemodel= ?, vehiclenumber= ?, vehicleyear= ?, emergencyname= ?,
emergencyaddress1= ?, emergencyaddress2= ?,emergencylandphone= ?,
emergencymobilephone= ?, isprofilecomplete = ? WHERE username = ?"))
{
$stmt->bind_param('sssssississsssssssssssssssssi', $fullname, $sodowo,
addressline1, $addressline2, $city, $stateid, $pin, $birthdate, $bloodgroup,
$allergydetails, $pancardno, $officephone, $residencephone, $mobilephone,
$drivinglicensenumber, $drivinglicensevalidupto, $fmscidrivinglicensenumber,
$fmscientrantlicensenumber, $vehiclemake, $vehiclemodel, $vehiclenumber, $vehicleyear,
$emergencyname, $emergencyaddress1, $emergencyaddress2, $emergencylandphone,
$emergencymobilephone, $isprofilecomplete , $username );
$stmt->execute();
$stmt->close();
}
When the above update statement is executed it is updating all the rows with the values instead of the WHERE clause. Any ideas why this is happening?
Thanks.

The last value of the types string for bind param (first parameter ("sssssississsssssssssssssssssi") is an "i" for integer but you're comparing it to "username" which is probably a string.
I guess the value you're passing in is converted to 0 and comparing 0 to any string in MySQL is always true (see mysql: why comparing a 'string' to 0 gives true?).
Try changing the last "i" for a "s" in "sssssississsssssssssssssssssi" (which is really horrible to read and hence very error-prone btw.)

Related

PHP 8.0.8 / MYSQL ArgumentCountError: The number of elements in the type definition string must match the number of bind variables [duplicate]

So I have this massive headache inducing query that I need to perform involving 65 form inputs needing to be injected into a database using mysqli prepared statements.
The issue I'm running into is that it says the # of variables I am attempting to call bind_param on does not match the # of "s"'s that I am using. I counted a dozen times and do not see where I am going wrong here. There are 65 variables, and 65 "s"'s.
Can anyone see something I'm missing? Or am I perhaps using the bind_param method in an incorrect manner?
// Preparing our query statement via mysqli which will auto-escape all bad characters to prevent injection
$query3 = 'INSERT INTO datashep_AMS.COMPLETE_APPLICATIONS (
project_name,
status,
funding_requested,
project_title,
program,
county,
parish,
name_of_watercourse,
which_is_a_tributary_of,
name_of_applicant,
contact_person_or_project_supervisor,
relationship_to_organization,
business_phone,
home_phone,
email,
signature_of_thesis_or_study_supervisor,
mailing_address,
postal_code,
website,
mailing_address_for_payment,
hst_registration_no,
total_cost_dollar,
total_cost_percent,
dollar_amount_requested_from_nbwtf,
percent_amount_requested_from_nbwtf,
descriptive_summary,
background_of_organization,
mandate,
years_in_existence,
membership,
accomplishments,
previous_project_name,
previous_project_number,
previous_project_amount_received_from_nbwtf,
summary_of_activities,
summary_of_Results,
project_title_2,
reason_and_or_purpose,
objectives,
project_description,
methods,
equipment_and_materials_required,
personnel_required,
proposed_start_date,
proposed_end_date,
type_of_data_to_be_stored,
where_will_it_be_housed,
monitoring,
short_term_achievement,
long_term_achievement,
previous_studies,
required_permits,
consultants,
short_term_commitment,
long_term_commitment,
project_duration,
project_evaluation,
promotion_of_project,
promotion_of_client,
publication_of_results,
community_benefits,
effects_on_traditional_uses,
possible_changes_in_public_access_to_areas,
possible_impact_on_wildlife_and_or_environment,
likelihood_of_future_requests_for_funding,
list_all_other_funding_sources_for_this_project
) VALUES (
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?
)';
// "Preparing" the query using mysqli->prepare(query) -- which is the equivalent of mysql_real_escape_string -- in other words, it's the SAFE database injection method
$stmt = $dbConnection->prepare($query3);
// "Bind_param" == replace all the "?"'s in the aforementioned query with the variables below
$stmt->bind_param("s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s", $project_name, $status, $funding_requested, $project_title, $program, $county, $parish, $name_of_watercourse, $which_is_a_tributary_of, $name_of_applicant, $contact_person_or_project_supervisor, $relationship_to_organization, $business_phone, $home_phone, $email, $signature_of_thesis_or_study_supervisor, $mailing_address, $postal_code, $website, $mailing_address_for_payment, $hst_registration_no, $total_cost_dollar, $total_cost_percent, $dollar_amount_requested_from_nbwtf, $percent_amount_requested_from_nbwtf, $descriptive_summary, $background_of_organization, $mandate, $years_in_existence, $membership, $accomplishments, $previous_project_name, $previous_project_number, $previous_project_amount_received_from_nbwtf, $summary_of_activities, $summary_of_Results, $project_title_2, $reason_and_or_purpose, $objectives, $project_description, $methods, $equipment_and_materials_required, $personnel_required, $proposed_start_date, $proposed_end_date, $type_of_data_to_be_stored, $where_will_it_be_housed, $monitoring, $short_term_commitment, $long_term_achievement, $previous_studies, $required_permits, $consultants, $short_term_commitment, $long_term_commitment, $project_duration, $project_evaluation, $promotion_of_project, $promotion_of_client, $publication_of_results, $community_benefits, $effects_on_traditional_uses, $possible_changes_in_public_access_to_areas, $possible_impact_on_wildlife_and_or_environment, $likelihood_of_future_requests_for_funding, $list_all_other_funding_sources_for_this_project);
// Perform the actual query!
$stmt->execute();
The number of characters in the type definition string must be equal to the number of placeholders (? marks) in the SQL query.
// three ? marks
$stmt->prepare("INSERT INTO table (one, two, three) VALUES (?,?,?)");
$stmt->bind_param("sss", $one, $two, $three);
// three s characters (and three variables as well)
Note that characters in the type definition string should not be separated by commas.
You can see this format demonstrated in the examples on the manual page.
there are 65 string params so if there are 65 s's you have the correct number. However the errors are appearing because you separated the s's by commas. Instead of $stmt->bind_param("s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s..."
it should be
$stmt->bind_param("sssssssssssssssss..."
This should solve your errors.
The character in the bind_param should not be separated by a comma.
If you have to bind two variables do this:
$stmt->bind_param('ss', $firstvariable, $secondvariable);

mysqli_stmt::bind_param() not recognize new elelemt [duplicate]

So I have this massive headache inducing query that I need to perform involving 65 form inputs needing to be injected into a database using mysqli prepared statements.
The issue I'm running into is that it says the # of variables I am attempting to call bind_param on does not match the # of "s"'s that I am using. I counted a dozen times and do not see where I am going wrong here. There are 65 variables, and 65 "s"'s.
Can anyone see something I'm missing? Or am I perhaps using the bind_param method in an incorrect manner?
// Preparing our query statement via mysqli which will auto-escape all bad characters to prevent injection
$query3 = 'INSERT INTO datashep_AMS.COMPLETE_APPLICATIONS (
project_name,
status,
funding_requested,
project_title,
program,
county,
parish,
name_of_watercourse,
which_is_a_tributary_of,
name_of_applicant,
contact_person_or_project_supervisor,
relationship_to_organization,
business_phone,
home_phone,
email,
signature_of_thesis_or_study_supervisor,
mailing_address,
postal_code,
website,
mailing_address_for_payment,
hst_registration_no,
total_cost_dollar,
total_cost_percent,
dollar_amount_requested_from_nbwtf,
percent_amount_requested_from_nbwtf,
descriptive_summary,
background_of_organization,
mandate,
years_in_existence,
membership,
accomplishments,
previous_project_name,
previous_project_number,
previous_project_amount_received_from_nbwtf,
summary_of_activities,
summary_of_Results,
project_title_2,
reason_and_or_purpose,
objectives,
project_description,
methods,
equipment_and_materials_required,
personnel_required,
proposed_start_date,
proposed_end_date,
type_of_data_to_be_stored,
where_will_it_be_housed,
monitoring,
short_term_achievement,
long_term_achievement,
previous_studies,
required_permits,
consultants,
short_term_commitment,
long_term_commitment,
project_duration,
project_evaluation,
promotion_of_project,
promotion_of_client,
publication_of_results,
community_benefits,
effects_on_traditional_uses,
possible_changes_in_public_access_to_areas,
possible_impact_on_wildlife_and_or_environment,
likelihood_of_future_requests_for_funding,
list_all_other_funding_sources_for_this_project
) VALUES (
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?,
?
)';
// "Preparing" the query using mysqli->prepare(query) -- which is the equivalent of mysql_real_escape_string -- in other words, it's the SAFE database injection method
$stmt = $dbConnection->prepare($query3);
// "Bind_param" == replace all the "?"'s in the aforementioned query with the variables below
$stmt->bind_param("s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s", $project_name, $status, $funding_requested, $project_title, $program, $county, $parish, $name_of_watercourse, $which_is_a_tributary_of, $name_of_applicant, $contact_person_or_project_supervisor, $relationship_to_organization, $business_phone, $home_phone, $email, $signature_of_thesis_or_study_supervisor, $mailing_address, $postal_code, $website, $mailing_address_for_payment, $hst_registration_no, $total_cost_dollar, $total_cost_percent, $dollar_amount_requested_from_nbwtf, $percent_amount_requested_from_nbwtf, $descriptive_summary, $background_of_organization, $mandate, $years_in_existence, $membership, $accomplishments, $previous_project_name, $previous_project_number, $previous_project_amount_received_from_nbwtf, $summary_of_activities, $summary_of_Results, $project_title_2, $reason_and_or_purpose, $objectives, $project_description, $methods, $equipment_and_materials_required, $personnel_required, $proposed_start_date, $proposed_end_date, $type_of_data_to_be_stored, $where_will_it_be_housed, $monitoring, $short_term_commitment, $long_term_achievement, $previous_studies, $required_permits, $consultants, $short_term_commitment, $long_term_commitment, $project_duration, $project_evaluation, $promotion_of_project, $promotion_of_client, $publication_of_results, $community_benefits, $effects_on_traditional_uses, $possible_changes_in_public_access_to_areas, $possible_impact_on_wildlife_and_or_environment, $likelihood_of_future_requests_for_funding, $list_all_other_funding_sources_for_this_project);
// Perform the actual query!
$stmt->execute();
The number of characters in the type definition string must be equal to the number of placeholders (? marks) in the SQL query.
// three ? marks
$stmt->prepare("INSERT INTO table (one, two, three) VALUES (?,?,?)");
$stmt->bind_param("sss", $one, $two, $three);
// three s characters (and three variables as well)
Note that characters in the type definition string should not be separated by commas.
You can see this format demonstrated in the examples on the manual page.
there are 65 string params so if there are 65 s's you have the correct number. However the errors are appearing because you separated the s's by commas. Instead of $stmt->bind_param("s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s..."
it should be
$stmt->bind_param("sssssssssssssssss..."
This should solve your errors.
The character in the bind_param should not be separated by a comma.
If you have to bind two variables do this:
$stmt->bind_param('ss', $firstvariable, $secondvariable);

Speeding up an insert/ignore between database server connections

I've successfully refactored the below script to select records from a table on server 1, and then connect to server 2 and insert/ignore the missing records into the cloned table there.
This works but takes about 1.5 minutes to run. I'm hoping someone can help with a slightly faster and more efficient way of doing this, since it's successful but expensive.
I don't have the option to do federated storage or replication, so this has to be done with a script. I previously did this by using the max ID of the source table but after the insert I was missing up to 15 records a day.
Here's the script:
$source_data = mysqli_query($conn,
"select * from `cdrdb`.`session` where ts >= now() - INTERVAL 1 DAY");
while($source = $source_data->fetch_assoc()) {
//Insert new rows into ambition.session
$stmt = $conn2->prepare(
"INSERT IGNORE INTO ambition.session (SESSIONID,
SESSIONTYPE,CALLINGPARTYNO,FINALLYCALLEDPARTYNO,
DIALPLANNAME,TERMINATIONREASONCODE,ISCLEARINGLEGORIGINATING,
CREATIONTIMESTAMP,ALERTINGTIMESTAMP,CONNECTTIMESTAMP,DISCONNECTTIMESTAMP,
HOLDTIMESECS,LEGTYPE1,LEGTYPE2,INTERNALPARTYTYPE1,INTERNALPARTYTYPE2
,SERVICETYPEID1,SERVICETYPEID2,EXTENSIONID1,EXTENSIONID2,
LOCATION1,LOCATION2,TRUNKGROUPNAME1,TRUNKGROUPNAME2,SESSIONIDTRANSFEREDFROM
,SESSIONIDTRANSFEREDTO,ISTRANSFERINITIATEDBYLEG1,
SERVICEEXTENSION1,SERVICEEXTENSION2,SERVICENAME1,
SERVICENAME2,MISSEDUSERID2,ISEMERGENCYCALL,NOTABLECALLID,
RESPONSIBLEUSEREXTENSIONID,
ORIGINALLYCALLEDPARTYNO,ACCOUNTCODE,ACCOUNTCLIENT,ORIGINATINGLEGID
,SYSTEMRESTARTNO,PATTERN,HOLDCOUNT,AUXSESSIONTYPE,
DEVICEID1,DEVICEID2,ISLEG1ORIGINATING,ISLEG2ORIGINATING,
GLOBALCALLID,CADTEMPLATEID,CADTEMPLATEID2,ts,INITIATOR,
ACCOUNTNAME,APPNAME,CALLID,CHRTYPE,CALLERNAME,serviceid1,serviceid2)
VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
or die(mysqli_error($conn2)) ;
mysqli_stmt_bind_param($stmt,
"iisssiissssiiiiiiiiissssiiissssiiiisssiisiiiiiiiiisisssisii"
,$source['SESSIONID']
,$source['SESSIONTYPE']
,$source['CALLINGPARTYNO']
//omitting other columns for sake of space
);
$stmt->execute() or die(mysqli_error($conn2));
}
A simple improvement would be to move the call to prepare() to before the loop. Since the prepared statement is the same each time through the loop, there's no need to contact the DB server each time.
You can also move the call to bind_param() outside the loop, since the variables are the same each time. bind_param binds to a reference, so updating the variable will change what gets inserted when you call execute().
However, these are likely to make only a small difference. One of the most effective ways to improve speed of INSERT queries is to insert multiple rows at a time. This is much easier to do with PDO than mysqli, because you can provide an array of parameters in the call to $stmt->execute(). The code would look like:
$params = array();
$count = 0;
$batch_size = 100;
$placeholders = implode(", ", array_fill(0, $batch_size, "(SESSIONID,
SESSIONTYPE,CALLINGPARTYNO,FINALLYCALLEDPARTYNO,
DIALPLANNAME,TERMINATIONREASONCODE,ISCLEARINGLEGORIGINATING,
CREATIONTIMESTAMP,ALERTINGTIMESTAMP,CONNECTTIMESTAMP,DISCONNECTTIMESTAMP,
HOLDTIMESECS,LEGTYPE1,LEGTYPE2,INTERNALPARTYTYPE1,INTERNALPARTYTYPE2
,SERVICETYPEID1,SERVICETYPEID2,EXTENSIONID1,EXTENSIONID2,
LOCATION1,LOCATION2,TRUNKGROUPNAME1,TRUNKGROUPNAME2,SESSIONIDTRANSFEREDFROM
,SESSIONIDTRANSFEREDTO,ISTRANSFERINITIATEDBYLEG1,
SERVICEEXTENSION1,SERVICEEXTENSION2,SERVICENAME1,
SERVICENAME2,MISSEDUSERID2,ISEMERGENCYCALL,NOTABLECALLID,
RESPONSIBLEUSEREXTENSIONID,
ORIGINALLYCALLEDPARTYNO,ACCOUNTCODE,ACCOUNTCLIENT,ORIGINATINGLEGID
,SYSTEMRESTARTNO,PATTERN,HOLDCOUNT,AUXSESSIONTYPE,
DEVICEID1,DEVICEID2,ISLEG1ORIGINATING,ISLEG2ORIGINATING,
GLOBALCALLID,CADTEMPLATEID,CADTEMPLATEID2,ts,INITIATOR,
ACCOUNTNAME,APPNAME,CALLID,CHRTYPE,CALLERNAME,serviceid1,serviceid2)"));
$stmt = $pdo->prepare("INSERT INTO ambition.sentence (<columns>) VALUES $placeholders");
while ($row = $source_data->fetch(PDO::FETCH_NUM)) {
$params += $row; // Append this row to $params
$count++;
if ($count != $batch_size) {
continue;
}
$stmt->execute($params);
// Reset variables for next batch
$params = array();
$count = 0;
}
if ($count) { // Handle the last batch that isn't the full size
$placeholders = implode(", ", array_fill(0, $count, "( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
$stmt = $pdo->prepare("INSERT INTO ambition.sentence (SESSIONID,
SESSIONTYPE,CALLINGPARTYNO,FINALLYCALLEDPARTYNO,
DIALPLANNAME,TERMINATIONREASONCODE,ISCLEARINGLEGORIGINATING,
CREATIONTIMESTAMP,ALERTINGTIMESTAMP,CONNECTTIMESTAMP,DISCONNECTTIMESTAMP,
HOLDTIMESECS,LEGTYPE1,LEGTYPE2,INTERNALPARTYTYPE1,INTERNALPARTYTYPE2
,SERVICETYPEID1,SERVICETYPEID2,EXTENSIONID1,EXTENSIONID2,
LOCATION1,LOCATION2,TRUNKGROUPNAME1,TRUNKGROUPNAME2,SESSIONIDTRANSFEREDFROM
,SESSIONIDTRANSFEREDTO,ISTRANSFERINITIATEDBYLEG1,
SERVICEEXTENSION1,SERVICEEXTENSION2,SERVICENAME1,
SERVICENAME2,MISSEDUSERID2,ISEMERGENCYCALL,NOTABLECALLID,
RESPONSIBLEUSEREXTENSIONID,
ORIGINALLYCALLEDPARTYNO,ACCOUNTCODE,ACCOUNTCLIENT,ORIGINATINGLEGID
,SYSTEMRESTARTNO,PATTERN,HOLDCOUNT,AUXSESSIONTYPE,
DEVICEID1,DEVICEID2,ISLEG1ORIGINATING,ISLEG2ORIGINATING,
GLOBALCALLID,CADTEMPLATEID,CADTEMPLATEID2,ts,INITIATOR,
ACCOUNTNAME,APPNAME,CALLID,CHRTYPE,CALLERNAME,serviceid1,serviceid2) VALUES $placeholders");
$stmt->execute($params);
}
For this to work as I've written it, you need to ensure that the columns returned by the SELECT query are in the same order as the list you're inserting. Avoid using SELECT * when doing this, so you don't get any surprises if there's a change in the schema of the source table.
You probably know by now that inserting one row at a time, one transaction per row, is the slowest way to load data.
I have tested different ways of loading data, and I gave a talk at Percona Live 2017:
Load Data Fast!
TL;DR: Use LOAD DATA INFILE, even if you have to dump your source data into a CSV file first.
Here's an example, though I have not tested it:
$all_columns = "
`SESSIONID`, `SESSIONTYPE`, `CALLINGPARTYNO`, `FINALLYCALLEDPARTYNO`,
`DIALPLANNAME`, `TERMINATIONREASONCODE`, `ISCLEARINGLEGORIGINATING`,
`CREATIONTIMESTAMP`, `ALERTINGTIMESTAMP`, `CONNECTTIMESTAMP`,
`DISCONNECTTIMESTAMP`, `HOLDTIMESECS`, `LEGTYPE1`, `LEGTYPE2`,
`INTERNALPARTYTYPE1`, `INTERNALPARTYTYPE2`, `SERVICETYPEID1`,
`SERVICETYPEID2`, `EXTENSIONID1`, `EXTENSIONID2`, `LOCATION1`, `LOCATION2`,
`TRUNKGROUPNAME1`, `TRUNKGROUPNAME2`, `SESSIONIDTRANSFEREDFROM`,
`SESSIONIDTRANSFEREDTO`, `ISTRANSFERINITIATEDBYLEG1`, `SERVICEEXTENSION1`,
`SERVICEEXTENSION2`, `SERVICENAME1`, `SERVICENAME2`, `MISSEDUSERID2`,
`ISEMERGENCYCALL`, `NOTABLECALLID`, `RESPONSIBLEUSEREXTENSIONID`,
`ORIGINALLYCALLEDPARTYNO`, `ACCOUNTCODE`, `ACCOUNTCLIENT`, `ORIGINATINGLEGID`,
`SYSTEMRESTARTNO`, `PATTERN`, `HOLDCOUNT`, `AUXSESSIONTYPE`, `DEVICEID1`,
`DEVICEID2`, `ISLEG1ORIGINATING`, `ISLEG2ORIGINATING`, `GLOBALCALLID`,
`CADTEMPLATEID`, `CADTEMPLATEID2`, `ts`, `INITIATOR`, `ACCOUNTNAME`, `APPNAME`,
`CALLID`, `CHRTYPE`, `CALLERNAME`, `serviceid1`, `serviceid2`"
$select_sql = "
SELECT $all_columns FROM `cdrdb`.`session`
WHERE ts >= NOW() - INTERVAL 1 DAY";
$source_data = mysqli_query($conn, $select_sql);
$tmpfilename = tempnam('/tmp', 'data');
fp = fopen($tmpfilename, 'w'); // do proper error handling and use
while ($source = $source_data->fetch_assoc()) {
fputcsv($fp, array_values($source));
}
fclose($fp);
$tmpfilename = mysqli_real_escape_string($conn2, $tmpfilename);
$load_sql = "
LOAD DATA LOCAL INFILE '$tmpfilename'
IGNORE INTO TABLE `ambition`.`session`
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
( $all_columns )";
$conn2->query($load_sql);

php mysql bind param parameters

I'm trying out using prepared statements for the first time and running into the following issue with the below code
Error :
Warning: mysqli_stmt_bind_param() expects parameter 1 to be
mysqli_stmt, boolean given
Code :
$stmt = mysqli_prepare($db, "INSERT INTO fragrances(name, description, essentialoils, topnotes, middlenotes, basenotes, reference, year, type, price, fragrancehouse, triangle, extractname, extractreference, extractprice, extractfragrancehouse, disccolour, collarcolour, actuatorcolour)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssssssssssssssssss', $name, $description, $essentialoils, $topnotes, $middlenotes, $basenotes, $reference, $year, $type, $price, $fragrancehouse, $triangle, $extractname, $extractreference, $extractprice, $extractfragrancehouse, $disccolour, $collarcolour, $actuatorcolour);
mysqli_stmt_execute($stmt);
I've looked at many different questions on here and none of their solutions seem to apply for my problem, does anyone know what the issue is?
$stmt becomes a boolean only when mysqli_prepare returns false.
When this happens it means it failed to prepare the query therefore you need to check for errors:
$stmt = mysqli_stmt_init($db);
if (mysqli_stmt_prepare($stmt, 'INSERT INTO fragrances VALUES...')) {
//it's all good bind and execute here
}else{
//we have a problem
printf("Errormessage: %s\n", mysqli_error($db));
}
The error message means your mysqli_prepare returned a boolean (and for your case, it returned false).
You need to replace all your field name by the character ? to make your prepared statement. This is how it works.
See example in the official documentation
EDIT See also mysqli_error , which will detail your error. In fact, you should always check a variable before using it:
$stmt = mysqli_prepare($db, "....");
if(!$stmt)
echo mysqli_error($db); // display error only for debug. Avoid this in production
It means your SQL was invalid because the prepare is returning false;
Your SQL should be;
$stmt = mysqli_prepare($db, "INSERT INTO fragrances VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )");
Each ? is to show where each parameter needs to be bound respectively.
Your INSERT statement is invalid: VALUES clause must be with ? in parantheses (and after field names in parentheses). Also good practice is to check $stmt after assigning:
$stmt = mysqli_prepare($db,
"INSERT INTO fragrances (name, description, essentialoils, topnotes, middlenotes, basenotes, reference, year, type, price, fragrancehouse, triangle, extractname, extractreference, extractprice, extractfragrancehouse, disccolour, collarcolour, actuatorcolour)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
if ($stmt) {
mysqli_stmt_bind_param($stmt, 'sssssssssssssssssss', $name, $description, $essentialoils, $topnotes, $middlenotes, $basenotes, $reference, $year, $type, $price, $fragrancehouse, $triangle, $extractname, $extractreference, $extractprice, $extractfragrancehouse, $disccolour, $collarcolour, $actuatorcolour);
mysqli_stmt_execute($stmt);
// ...
} else
printf("Error: %s\n", mysqli_error($db));

Where is the mysqli prepared statement query error? [duplicate]

This question already has answers here:
Can I parameterize the table name in a prepared statement? [duplicate]
(2 answers)
Closed 1 year ago.
I'm trying to create a mysqli prepared statement where I import tables from an odbc connected database into a mysql database, I'm getting this error with 106-column wide table query.
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '? (ID, column1, column2, column3, column4, ' at line 1"
When I echo out the query here it is...
INSERT INTO ? (ID, column1, column2, column3, column4, ...106 total columns... ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?)
$sql = "SELECT * FROM $table WHERE $key = '$acct'";
$link = getODBCConnection();
$result = odbc_do($link, $sql);
$data = array();
while ($row = odbc_fetch_array($result)) {
//store all query rows as array
array_push($data, $row);
}
//insert into mysql table of the same name
//get column count from first row
$columns = count($data[0]);
$params = str_repeat(" ?,",$columns);
$params = rtrim($params,',');
$types = str_repeat("s",$columns+1);
$fields = implode(", ", array_keys($data[0]));
$sql = "INSERT INTO ? ($fields) VALUES ($params) ON DUPLICATE KEY UPDATE";
echo $sql."<br>";
$link = getSalesConnection();
$stmt = $link->prepare($sql);
var_dump($link->error);
foreach ($data as $row) {
$stmt->bind_param($types, $table, implode(", ",array_values($row)));
$stmt->execute();
}
I've tried this using standard bind_param and also using the call_user_func_array() method. I've tried quoting my parameter strings and the column names, without effect. If there was an error with my bind_param types I should not have an error on the prepare statement should I? But there is some problem with the SQL going to the prepare command that I can't pinpoint. Please help!
Query parameters can be used in place of scalar values only. You can't parameterize table names, column names, SQL expressions, keywords, lists of values, etc.
WRONG: SELECT ?, b, c FROM t WHERE a = 1 ORDER BY b ASC
The parameter value will be a literal value, not the name of a column.
WRONG: SELECT a, b, c FROM ? WHERE a = 1 ORDER BY b ASC
Syntax error.
WRONG: SELECT a, b, c FROM t WHERE ? = 1 ORDER BY b ASC
The parameter value will be a literal value, not the name of a column.
WRONG: SELECT a, b, c FROM t WHERE a IN (?) ORDER BY b ASC
The parameter value will be a single literal value, not a list of values, even if you pass a string of comma-separated values.
WRONG: SELECT a, b, c FROM t WHERE a = 1 ORDER BY ? ASC
The parameter value will be a literal value, not the name of a column.
WRONG: SELECT a, b, c FROM t WHERE a = 1 ORDER BY b ?
Syntax error.
Basically if you could write a string literal, date literal, or numeric literal in place of the query parameter, it should be okay. Otherwise you have to interpolate the dynamic content into the SQL string before you prepare() it.
It looks as though the bind_param() function does not replace the very first '?' that defines the table name. Try manually putting the table name into the prepared string first and only use '?' markers where it is expecting values.

Categories