Php sql command simply clears database table? - php

When I try and run this query on my database:
$mysqli->query("UPDATE
catalogsearch_fulltext
SET data_index = '".$unique_string."'
WHERE MATCH(data_index) AGAINST ('".$savestring."')
AND store_id = '1'");
It not only doesn't work, but it clears my ENTIRE catalogsearch_fulltext table. What am I doing wrong? I'm somewhat new to SQL so this is hopefully a quick error someone can spot.
I can provide more code if requested, but I don't think it is applicable.
Thanks!
Edit:
$unique_string = "325-FBA-BA-0006-x3|Badger|Enabled|Taxable Goods|Badger - SPF 30+ Anti-Bug Sunscreen, 2.9oz. - (Pack of 3)|47300|You asked, and Badger listened! After receiving many requests for a totally natural combination bug repellent and sunscreen, Badger took their wildly popular SPF 30+ Sunscreen formula and combined it with their Anti-Bug Balm formula to create easy-to-apply, safe, and natural protection for the whole family!|43.35|1"
$string = "the same as above but with duplicat entries in the | Pipe | sections."
It is also worth noting that this query is in a loop that goes through about 6 records.

If $unique_string and $savestring were both uninitialised, I expect you would set your index column to null - which would result in them not showing up in any selects that use that index column?
Perhaps you meant $uniquestring and $save_string? or perhaps these variables are out of scope?

Related

PHP if comparison vs MySQL Where (Which is more efficient)

My situation: My website will look at a cookie for a remember me token and a user ID. If the cookie exists it will unhash it and look up the user ID and compare the token. with a "WHERE userid = '' and rememberme = ''".
My question is: Will MySQL optimize this query on the unique userid so that the query does not scan the entire database for this 20+ character token? Or instead should I just select the token from the database and then use a php if comparison to check if the tokens are the same?
In short (tl;dr): Would it be better to check if a token matches in with a MySQL select query, or to grab all the tokens from a databases database and compare the values with a php if conditional?
Thanks!
Simple answer:
YES, the database will definitely optimism your search AS LONG AS THE variable you are searching in the WHERE ... portion is indexed! You definitely should not retrieve all the information via SQL and then do a PHP conditional if you are worried about performance.
So if the id column in your table is not indexed, you should index it. If you have let say... 1 million rows already in your table and run a command like SELECT * FROM user WHERE id = 994321, you would see a definite increase in performance.
Elaborating:
A database (like MySQL) is made to be much faster at executing queries/commands than you would expect that to happen in php for instance. In your specific situation, lets say you are executing this SQL statement:
$sql = "SELECT * FROM users WHERE id = 4";
If you have 1 million users, and the id column is not indexed, MySQL will look through all 1 million users to find all the rows with id = 4. However, if it is indexed, there is something called a b tree that MySQL makes (behind the scenes) which works similarly to how the indexing of a dictionary work.
If you try to find the world slowly in a dictionary, you might open the book in the middle, find words that start with the letter M and then look in the middle again of the pages on your right side hoping to find a letter closer to S. This method of looking for a word is much faster than looking at each single page from the beginning 1 by 1.
For that very reason, MySQL has created indexes to help performance and this feature should definitely be taken advantage of to help increase the speed of your queries.
Comparing it on MySQL-side should be fast. It should find the corresponding row by ID first (fast) and then compare the hash (also fast, since there will be only 1 row to check).
Try analyzing the query with EXPLAIN to find out the actual execution plan.
In my opinion it will be always faster to use WHERE clause no matter what (real) database server will be used. Database engines have strong algorithms for searching data written in language that is compiling to low-level code dedicated to platform, so it cannot be even compared with some loop written in interpreted PHP.
And remember that for PHP loop you will have to send all records from DB to PHP.
If you Data Base its on a separate server than you Apache PHP there is not doubt it would be faster if you write a query in MySQL.
If your PHP and MySQL server is on the same physical server probably PHP would be faster cause the comparison will be made on the RAM But have all the User Id array into RAM would be a waste of RAM so you can use Indexes that would speed up your query
ALTER TABLE table ADD INDEX idx__tableName__fieldName (field)

MySQL table lock, or other possible solutions?

I have a security problem. I think to lock a table would be a solution, only I don't know how to properly do it in MySQL, PHP, and don't have enough time to search Google and documentations anymore.
So, the task:
Make a database and write a php code to randomly get lottery-tickets.
I have a table, that contains only a few row. (id, name, quantity)
So for example:
1 - no win - 20000
2 - Hello Kitty bag - 200
3 - a very nice pen - 50
etc.
I wrote the php, so the logic's the following:
1) Get the amount of evey tickets from the database, and create a PHP array that contains the intervals, like:
no win: 20000,
Hello Kitty bag: 20200,
a very nice pen: 20250.
2)Generate a random number from 1 to max, so I know what ticket the user got.
3)Update the database: subtract 1 from the proper row.
Now, this works great, however the problem:
What if I have a very large amount of users, and two or three of them clicks at the same time, random the same number, (lets assume it's hello kitty) but only have 1 of that item?
All the three of them subtract from the database, not stopping at 0. (In this example, we would have -2 hello kitty bag)
Huge issue, at least for me.
So in summary, my question is:
1)How can I lock the table from the selection, until I am ready to subtract? Is it a good solution?
2)Can I make it one query, or MySQL can't handle that?
3)Other solutions?
I appreciate every single answer, really!
Thanks in advance, also sorry for the long post, but wanted to keep things straight.
[ SOLVED ]
I used a stored procedure, here are the details.
I had some luck to have my server version above 5.x, since as I read the MyISAM system supports stored procedures only above this version.
I will write some code here hoping someone'll find it useful in the future:
delimiter //
CREATE PROCEDURE `name`(IN a_parameter INT(20))
DECLARE some_text VARCHAR(50) DEFAULT '';
#now using all this stuff
SELECT `name` INTO some_text FROM `users_table` WHERE `table_id` = a_parameter;
SELECT some_text
END//
delimiter ;
You need to use a transaction (documentation here), and a table lock (read about the interaction between table lock and transactions here).
To do it in one query you can build a stored procedure (documentation here). I will go with a procedure.
If you are using PHP PDO you can read all about in in the manual (here, most important PDO:: beginTransaction and PDO:: commit). If you are still using mysql extendion you need to do it explicit like this:
mysql_query('START TRANSACTION');
// Because you cannot nest lock's and transactions, this is a workaround to lock the table
mysql_query('SELECT * FROM foo FOR UPDATE'); // Lock issued, the important part is "FOR UPDATE"
//[ your query's here ]
// if something goes wront, revert the changes
mysql_query('ROLLBACK');
// at the end commit the changes
mysql_query('COMMIT');
Lookup "transactions".. Use mysqli/pdo and their transaction capabilities
http://tympanus.net/codrops/2009/09/01/using-mysql-transactions-with-php/
http://www.shotdev.com/php/php-mysql/php-mysql-and-transaction-begin-commit-rollback/
etc

How do I speed up a SQL UPDATE that also contains a JOIN on 25 million rows

the query i'd like to speed up (or replace with another process):
UPDATE en_pages, keywords
SET en_pages.keyword = keywords.keyword
WHERE en_pages.keyword_id = keywords.id
table en_pages has the proper structure but only has non-unique page_ids and keyword_ids in it. i'm trying to add the actual keywords(strings) to this table where they match keyword_ids. there are 25 million rows in table en_pages that need updating.
i'm adding the keywords so that this one table can be queried in real time and return keywords (the join is obviously too slow for "real time").
we apply this query (and some others) to sub units of our larger dataset. we do this frequently to create custom interfaces for specific sub units of our data for different user groups (sorry if that's confusing).
this all works fine if you give it an hour to run, but i'm trying to speed it up.
is there a better way to do this that would be faster using php and/or mysql?
I actually don't think you can speed up the process.
You can still add brutal power to your database by cluserting new servers.
Maybe I'm wrong or missunderstood the question but...
Couldn't you use TRIGGERS ?
Like... when a new INSERT is detected on "en_pages", doing a UPDATE after on that same row?
(I don't know how frequent INSERTS are in that table)
This is just an idea.
How often does "en_pages.keyword" and "en_pages.keyword_id" changes after being inserted ?!?!?
I don't know about mySQL but usually this sort of thing runs faster in SQL Server if you process a limited number of batches of records (say a 1000) at a time in a loop.
You might also consider a where clause (I don't know what mySQL uses for "not equal to" so I used the SQL Server verion):
WHERE en_pages.keyword <> keywords.keyword
That way you are only updating records that have a difference in the field you are updating not all of the them.

Query by slug or query by id?

Typically, when I make applications that need slugs in the URL, I query by the slug in the database to get the content (with an index on the slug field, of course). Using a typical LAMP stack (with PHP & MySQL), what is the advantage or disadvantage of doing this from a database perspective? Would it make more sense to always query by id and simply create some sort or route for slugs? Could this application design pose any security problems?
I'm using cakePHP, specifically, so if there are any cake-specific answers, that would be appreciated, but not necessary.
If you are absolutely positive that slug won't change, you can use it. But numbers are probably faster and safer (this one is for sure).
I just ran queries on a database with 1 000 000 rows, you can see that by ID is 230x faster (subject is not indexed though). Besides that, like Col Shrapnel said, what if you change the subject? Your URL will be broken, and you cannot remember every change in subject.
Numbers are numbers, computers work with numbers :) JK
SELECT tid FROM `forum_threads` WHERE subject = "New BMW X5";
Showing rows 0 - 0 (1 total, Query took 0.0230 sec)
SELECT tid FROM `forum_threads` WHERE tid = 19906;
Showing rows 0 - 0 (1 total, Query took 0.0001 sec)
Two things :
Keep in mind slug values often need to be unique.
Also, using an i18n database schema, SQL queries on the table need an additional Join (slug is usually related to language)

checking to see if data exist with in a table

How do i go about looking into a table and searching to see if a row exist. the back gorund behind it is the table is called enemies. Every row has a unique id and is set to auto_increment. Each row also has a unique value called monsterid. the monster id isn't auto_increment.
when a monster dies the row is deleted and replaced by a new row. so the id is always changing. as well the monsterid is changed too.
I am using in php the $_GET method and the monsterid is passing through it,
basically i am trying to do this
$monsterID = 334322 //this is the id passed through the $_GET
checkMonsterId = "check to see if the monster id exist within the enemies table"
if monsterid exist then
{RUN PHP}
else
{RUN PHP}
If you need anymore clarity please ask. and thanks for the help in advance.
Use count! If it returns > 0, it exists, else, it doesn't.
select count(*) from enemies where monsterid = 334322
You would use it in PHP thusly (after connecting to the database):
$monsterID = mysql_real_escape_string($monsterID);
$res = mysql_query('select count(*) from enemies where monsterid = ' . $monsterid) or die();
$row = mysql_fetch_row($res);
if ($row[0] > 0)
{
//Monster exists
}
else
{
//It doesn't
}
Use count, like
select count(*) from enemies where monsterid = 334322
However be sure to make certain you've added an index on monsterid to the table. Reason being that if you don't, and this isn't the primary key, then the rdbms will be forced to issue a full table scan - read every row - to give you the value back. On small datasets this doesn't matter as the table will probably sit in core anyway, but once the number of rows becomes significant and you're hitting the disk to do the scan the speed difference can easily be two orders of magnitude or more.
If the number of rows is very small then not indexing is rational as using an non-primary key index requires additional overhead when inserting data, however this should be a definite decision (I regularly impress clients who've used a programmer who doesn't understand databases by adding indexes to tables which were fine when the coder created them but subsequently slow to a crawl when loaded with real volumes of data - quite amazing how one line of sql to add an index will buy you guru status in your clients eyes cause you made his system usable again).
If you're doing more complex queries against the database using subselect, something like finding all locations where there is no monster, then look up the use of the sql EXISTS clause. This is often overlooked by programmers (the temptation is to return a count of actual values) and using it is generally faster than the alternatives.
Simpler :
select 1 from enemies where monsterid = 334322
If it returns a row, you have a row, if not, you don't.
The mysql_real_escape_string is important to prevent SQL injection.
$monsterid = mysql_real_escape_string($_GET['monsterid']);
$query = intval(mysql_query("SELECT count(*) FROM enemies WHERE monsterid = '$monsterid'));
if (mysql_result > 0) {
// monster exists
} else {
// monster doesn't exist
}

Categories