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);
Related
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);
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);
I have a quick question...I am updating all values in a row using a prepared statement and an array.
When initially inserting, my statement looks like this (and works perfect)
$sql="INSERT INTO $dbtable VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
The first and last values are NULL as the first is an auto increment ID field and last is a timestamp field.
Is there a way to keep my UPDATE statement as simple as my INSERT statement like this...
$sql="UPDATE $dbtable SET (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) WHERE `announcements`.`id` = $id LIMIT 1";
I realize this does not work as is due to the first value being an auto increment field, is there a value I could put into my array to 'skip' this field?
This may not be the best way to describe my question but if you need more info, please let me know!
Thank you in advance!
UPDATE has no "implicit columns" syntax like INSERT does. You have to name all the columns that you want to change.
One alternative you can use in MySQL is REPLACE:
REPLACE INTO $dbtable VALUES (?, ?, ?, ?, ?, ...)
That way you can pass the current value for your primary key, and change the values of other columns.
Read more about REPLACE here: https://dev.mysql.com/doc/refman/5.6/en/replace.html
Note that this is internally very similar to #Devon's suggestion of using two statements, a DELETE followed by an INSERT. For example, when you run REPLACE, if you have triggers, both the ON DELETE triggers are activated, and then the ON INSERT triggers. It also has side-effects on foreign keys.
The solution I can think of doesn't involve an UPDATE at all.
DELETE FROM $dbtable WHERE id = $id;
INSERT INTO $dbtable VALUES ($id, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
Since you don't want to use the UPDATE syntax, this would delete the row and add a new row with the same id, essentially updating it. I would recommend wrapping it in a transaction so you don't lose your previous row if the insert fails for any reason.
This question already has answers here:
mysqli_stmt::execute() expects exactly 0 parameters, 1 given
(4 answers)
Closed 1 year ago.
During my paths of coding in Mysqli I have been stumped and can't seem to figure out what the error is trying to say:
Warning: mysqli_stmt::execute() expects exactly 0 parameters, 1 given in /home/test/private_html/test.php on line 58
The code I have tried to fix many times is as so
$stmt = $mysqli->prepare("INSERT INTO `test_table`(datenow,test1,test2,test3,test4,test5,test6,test7,test8,
test9,test10,test11,test12,test14,test15,test16,test17,test18,)
VALUES (CURRENT_TIMESTAMP, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
$stmt->bind_param('ssssssssssssssssss',$test1,$test2,$test3,$test4,$test5,$test6,$test7,$test8,$test9,$test10,$test11,$test12,$test13,$test14, $test15,$test16,$test17,$test18);
$stmt->execute(array($test1,$test2,$test3,$test4,$test5,$test6,$test7,$test8,$test9,$test10,$test11,$test12,$test13,$test14,$test15, $test16,$test17,$test18
));
And the line 58 would be:
));
It should be:
$stmt->execute();
You don't provide the values when calling execute, you provided them when you called bind_param.
It seems like you're confusing mysqli with PDO.
$stmt = $mysqli->prepare("INSERT INTO `test_table`(datenow,test1,test2,test3,test4,test5,test6,test7,test8,
test9,test10,test11,test12,test14,test15,test16,test17,test18,)
VALUES (CURRENT_TIMESTAMP, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
$stmt->bind_param('ssssssssssssssssss',$test1,$test2,$test3,$test4,$test5,$test6,$test7,$test8,$test9,$test10,$test11,$test12,$test13,$test14, $test15,$test16,$test17,$test18);
$stmt->execute();
$stmt->execute();
That is enough already mate.
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.