In php, I'm trying to insert a value into one table, return an auto-incremented value, and then insert that value along with other values into a second table.
I'm running into a few problems. First, while there's a lot of ways of doing this in SQL, I have to do this with php's mysql functions. I'm afraid of weird errors if I combine multiple statements together. Second, like I mentioned, I need this to be done in one query, as it'll be used for a web application.
My current query is like this
INSERT INTO TABLE1 VALUES(*);
INSERT INTO TABLE2
SELECT max(AutoIncrementedColumn)
FROM TABLE1;
The problem I'm having is that mysql_query() doesn't support multi queries. Also, I believe mysql_escape_string() removes anything it believes to be a multi query, so even if I could somehow get mysql_query to believe my query is not a multi query, I'm still out of luck unless I write my own escape method.
Does anyone have any ideas on how to deal with this problem?
EDIT: Forgot to mention that I can't use mysql_insert_id because the column that's autoincrementing is of type Bigint.
Related
Until recently I've been using mysql_real_escape_string() to fix most of my variables before making SQL queries to my database. A friend said that I should be using PDO's prepared statements instead, so after reading a bit about them I'm now switching over to them.
I've only encountered one problem so far in switching over, and that's counting the rows to returned by a SELECT statement. On occasion in my code, I'd run an SQL query and then count the number of rows returned from the SELECT statement. Depending on whether a result set returned, I would take different actions. Sometimes I do need to use the result set from it. MySQL let me go straight to mysql_fetch_assoc() after mysql_num_rows() with no problem. However, PDO doesn't seem to have anything like mysql_num_rows().
I've been reading some responses on SO that gave me a solution, to either use COUNT() in the SQL statement or to use the PHP function count() on the result set. COUNT() would work fine in the SQL statement if I didn't need the result set in some places, however, several people have mentioned that using count() on the result set is fairly inefficient.
So my question is, how should I be doing this if I need to count the number of rows selected (if any), then run a script with the result set? Is using count() on the result set the only way in this case, or is there a more efficient way to do things?
Below is a short example of something similar to my previous SQL code:
$query=mysql_query('SELECT ID FROM Table WHERE Name='Paul' LIMIT 1);
if(mysql_num_rows($query)>0)
{
print_r(mysql_fetch_assoc($query));
}
else
{
//Other code.
}
Thanks.
EDIT
I do know that you use fetchAll() on the statement before counting the result set (which gives me what I need), but I'm just trying to figure out the most efficient way to do things.
$stmt->rowCount();
http://php.net/manual/en/pdostatement.rowcount.php
the rows must be fetched(buffered into memory, or iterated) for it to work. It's not uncommon for your pdo driver to be configured to do this automatically.
You will have to use Count(). You can run two queries like
SELECT COUNT(ID) FROM Table WHERE Name='Paul'
one you have get the count, then run the query with select clause
SELECT ID FROM Table WHERE Name='Paul' LIMIT 1
Count() function is not inefficient at all if you are using it like COUNT(ID), because most probably id is primary key and have an index. MYSQL wont even have to access the table.
I have a MySQL table with ID as a primary key and other for this matter non-important fields.
What I would like to do is delete multiple records by sending a list of IDs for deletion as a parameter to stored procedure.
I know how to do this manually (building a query directly in PHP) but I would like to avoid that and do all my SQL directly in the DB.
Tried searching SO but couldn't find any related questions. Sorry if this is a duplicate.
Thanks
In accordance to http://dev.mysql.com/doc/refman/5.1/en/faqs-stored-procs.html#qandaitem-B-4-1-17 you can't do it directly.
But I think you can try to the following trick:
Create string of you ids in php like 'id1,id2,id3'.
Use prepared statement for binding this sting on fly.
Maybe it helps.
You could try something like
DELETE FROM sometable WHERE FIND_IN_SET(idfield, #param)
no idea if this'd work (and don't have access to a mysql instance right now to test on). Basically the problem is that if you pass in a comma-separated value list into a paramter, it'll just be a string inside the sproc, and doing a WHERE id IN ('1,2,3') would fail, since that's just a simple string and not at all the same as WHERE id IN (1,2,3). The find_in_set() function should take care of that.
I gave +1 to #Marc B for clever use of FIND_IN_SET(). It won't be able to use an index, so the performance won't be good, but it should work.
Another solution that can work (but will be slow as well, because it can't use an index):
DELETE FROM sometable
WHERE CONCAT(',', param, ',') LIKE CONCAT('%,', idfield, ',%')
The solution that #Andrej L describes isn't really parameter binding, it's interpolation of a stored procedure argument into a dynamic SQL string prior to preparing it.
SET sql = CONCAT('DELETE FROM sometable WHERE idfield IN (', param, ')');
PREPARE stmt FROM sql;
EXECUTE stmt;
You can't parameterize a list of values with a single parameter, even if the parameter's value looks like a comma-separated list of integers.
Interpolation can work, and it will benefit from an index, but be careful to filter the string so it contains only numeric digits and commas. Otherwise you introduce a significant risk of SQL injection (debunking the claim that some people make that stored procedures are inherently more secure).
Im writing PHP scripts for using with my mySQL database. The only problem i have is binding variables for drop table/ create table and so on.
$stmt = $link->prepare("DROP TABLE ?");
$stmt->bind_param('s','testing');
$stmt->execute();
is not working. I tried also:
SELECT * FROM (SELECT MAX(name) from profiles where name='testing') <- is working
DROP TABLE (SELECT MAX(name) from profiles where name='testing') <- dont work
Binding a parameter is not the same as just replacing a portion of the string : you cannot just bind anything you want.
In this case : you cannot use a bound parameter for a table name -- you'll have to use string concatenations to build your query, instead of using a prepared statement.
As a reference, quoting PREPARE Syntax :
Parameter markers can be used only
where data values should appear, not
for SQL keywords, identifiers, and so
forth.
As far as I know, you can only bind to a parameter, not to any part of a query you want. You're essentially telling the database "hey, I'm going to pass you a value here, and I want you to do your magic to make sure it doesn't overstep its bounds". Things like table names or field names aren't values, they're part of the table structure itself.
In this case, you'll have to just use a use a simple $query = "DROP TABLE " . $table;. It should be easy enough to check against a list of known tables to ensure you're not injecting anything harmful. Anything that makes DDL changes shouldn't be taking input from the user anyway, as far as I'm concerned. These sorts of changes can be based on user input, but the actual construction of the query should be really well known and shouldn't need outside data to construct.
Also, I'm not really sure what you're trying to do with this query:
DROP TABLE (SELECT MAX(name) from profiles where name='testing');
It looks like you might be trying to delete a record, but that's entirely the wrong syntax for that. If you're trying to drop a table whose name comes from the result of another query, I really don't think you can do that either. I'm 99% sure that DROP TABLE expects only a literal table name value.
Are you sure you want to drop tables dynamically?
It is extremely unusual.
It seems you have wrong database design.
And now you faced a consequence.
It seems you should have one table users and delete rows from it, not tables.
I have these tables: My final mysql db, could someone check if the tables are correctly made?
How can I make an Insertion of an ad here?
Is join used on insert also?
Thanks
Clarification: I need to insert values into multiple tables here, and don't know how to do it else than using multiple INSERT INTO statements.
So I wonder if there is anyway to make just ONE statement (one line) and use JOIN to INSERT?
As far as I'm aware of, you can't INSERT data into multiple tables Within one plain SQL statement.
There are many database abstraction frameworks out there which can do something like that (DOCTRINE TO THE RESCUE!!) but thats a whole other story.
SQL for it self it not capable of such things.
No it's not possible with an INSERT statement to insert into multiple tables. But you could use a stored procedure that would nicely batch the various inserts, and the application would have only one SQL command to emit.
I don't understand your first question about the ads. As for the second, JOIN will not be used on a standard table unless you are using it in an INSERT...SELECT statement, which you very likely aren't.
I've recently started work on a new project using PHP5 and want to use their PDO classes for it. The problem is that the MySQL PDO Driver doesn't support rowCount() so there's no way to run a query and then get the number of affected rows, or rows returned, which is a pretty big issue as far as I'm concerned. I was wondering if anyone else has dealt with this before and what you've done to work around it. Having to do a fetch() or fetchAll() to check if any rows were affected or returned seems like a hack to me, I'd rather just do $stmt->numRows() or something similar.
You can issue a SELECT FOUND_ROWS() query right after the original SELECT query to get row count.
$pdo->query("SELECT * FROM users");
$foundRows = $pdo->query("SELECT FOUND_ROWS()")->fetchColumn();
See also: MySQL Docs on FOUND_ROWS()
For those of you who are using MySQL stored procedures, this solution isn't really feasible. What I would suggest that you do is have your stored procedure create two rowsets. The first one will contain one row and one column, containing the number of records. The second will be the recordset you will use for fetching that number of rows.
The number of unlimited rows can be a SELECT COUNT(*) with the exact same WHERE clause as the second rowset without the LIMIT/OFFSET clauses.
Another idea could be to create a temporary table. Use your SELECT statement to populate the temporary table. Then you can use SELECT COUNT(*) FROM tmpTable for your first rowset and SELECT * FROM tmpTable for your second.
This question is based on several false assumptions and one outdated statement.
First of all, do not confuse number of affected and selected rows. PDO supported the former even back in '09.
Speaking of number of rows returned by SELECT statement - you just don't need that number. The data you have is enough.
And yeah, nowadays rowCount() supports number of rows selected from mysql as well. But again - you don't need that number in an average web-application anyway.