I am trying to append strings to a field if they do not already exist with:
mysql_query("UPDATE gals4 SET tags = CONCAT(tags, '$instag') WHERE id = '$instagnum' AND tags NOT LIKE '$instag'");
This just appends to 'tags' regardless of weather it exists in the field or not. What am i doing wrong here?
To answer your immediate question, you must put the character % at the beginning and end of the match string:
"AND tags NOT LIKE '%$instag%'"
However, you should be aware that this is a terrible way to store data in an SQL database. There are at least three problems:
If you have tags that embed other tags ("cat" and "scat" for instance) you will find the wrong records unless you write very complicated comma-based searches.
These searches can never be indexed and will therefore become very slow as the number of records grows.
You cannot verify the tags used against a list of allowed tags, guarantee that only allowed tags are in the database, or easily present a list of existing or allowed tags.
The correct solution is to add at least one table to your database, called something like gals_tags, with columns galid and tag. Insert one record per tag into this table. If a gal has more than one tag, add one record for each tag.
You need another variable $instagwildcard which would be $instag but with a % after (and possibly before) $instag
As written, your select is looking for a string that is not an exact match to $instag - and I assume you are looking to also exclude strings that contain $instag somewhere in the string rather than an exact match....
$instagwildcard = "%" . $instag . "%";
mysql_query("UPDATE gals4 SET tags = CONCAT(tags, '$instag') WHERE id = '$instagnum' AND tags NOT LIKE '$instagwildcard'");
But I also agree with Larry's comment.
Related
I'm sure that there is a stupidly simple solution to this, but unfortunately my google-fu is too weak to find it.
I have a number of different tables for sizing, all following the same naming convention i.e size_001, size_002 etc. Within a loop I need to get the size entry that matches with the results already found.
Unfortunately there are no totally unique identifiers, as they repeat in each table (roman numerals for sizing). But they are unique in each individual table. So what I've tried so far looks a little bit like this:
SELECT * FROM CONCAT('size_00', '.$sizeTableID[$j].') WHERE sizeName LIKE '$sizeNames[$j]'"
Where $sizeTableId is a number from 1-9 and sizeName is a string e.g II or VI or, occasionally (because there's no consisitency), 2 etc
I've also tried ''$var'' inside the CONCAT and not using the CONCAT at all. Really I just need a way to join the database.size_00 and an integer variable.
If I understand correctly, this is actually simple:
$tablename = 'size00'.$sizeTableID[$j];
$sql = "SELECT * FROM $tablename WHERE sizeName LIKE '{$sizeNames[$j]}'";
and I think that solves it.
PHP is a bit quirky here.....
Try this one (when the variable is from an array/object, surround it with {})
$sql = "SELECT * FROM CONCAT('size_00', '{$sizeTableID[$j]}') WHERE sizeName LIKE '{$sizeNames[$j]}'";
I'm using Wordpress and trying to find pages that contain a shortcode and its attributes.
Here's some example content in a page
[my-shortcode title="some text" style="grid"
post_ids="45724,1786,1889,1927,2613,32856,2976,2898,2372,2059"
image_id="61690"]
I currently have this MySQL query with a regex. $my_id = a specific number I set.
$query = 'SELECT ID,post_content from ' . $wpdb->posts .
' where post_type="page"
and post_content regexp "\[my-shortcode[^\]].*post_ids=\"[^\"].*' .
$my_id . '[^\"].*\"[^\]].*image_id=\"[0-9].*\"[^\]]?\]"';
This seems to work fine except for the first ID in the post_ids attribute. It never matches the first one, only IDs after the first one.
No doubt I'm doing something monumentally obvious but I'm sadly not a regex whizz.
I also appreciate there's other ways I could query the DB in Wordpress but for many other reasons I wont go in to right now this is the way I need to do it.
Any help very much appreciated!
Answer found (syntax): The column name of my string had to be encased in backticks " ` " as they contained spaces. Note that this means that the majority of this post has no relevance to the issue. The code has been corrected in case someone wants to do something similar.
So, I am doing a foreach loop to assign a value (1/0) to non-static columns in my database (it needs to support addition/deletion/editing of columns). I am using $connectionvar->query($queryvar); to do my queries which worked fine up until now when I'm trying to use a custom built string as $queryvar in order to change the column name to a variable within the loop. I've been outputting this string through echo and it looks exactly like my functional queries but somehow doesn't run. I've attempted to use eval() to solve this but to no avail (I feel safe using eval() as the user input is radio buttons).
Here's the loop as well as my thought processes behind the code. If something seems incoherent or just plain stupid, refer to my username.
foreach($rdb as $x) { //$rdb is a variable retrieved from $_POST earlier in the code.
$pieces = explode("qqqppp", $x); //Splits the string in two (column name and value) (this is a workaround to radio buttons only sending 1 value)
$qualname = $pieces[0]; //Column name from exploded string
$qualbool = $pieces[1]; //desired row value from exploded string
$sql = 'UPDATE users SET '; //building the query string
$sql .= '`$qualname`';
$sql .= '=\'$qualbool\' WHERE username=\'$profilename\''; //$profilename is retrieved earlier to keep track of the profile I am editing.
eval("\$sql = \"$sql\";"); //This fills out the variables in the above string.
$conn->query($sql); //Runs the query (works)
echo ' '.$sql.' <br>'; //echoes the query strings on my page, they have the exact same output format as my regular queries have.
}
}}
Here's an example of what the echo of the string looks like:
UPDATE users SET Example Qualification 3='1' WHERE username='Admin2'
For comparison, echoing a similar (working) query variable outside of this loop (for static columns) looks like this:
UPDATE users SET profiletext='qqq' WHERE username='Admin2'
As you can see the string format is definitely as planned, yet somehow doesn't execute. What am I doing wrong?
PS. Yes I did research this to death before posting it, as I have hundreds of other issues since I started web developing a month ago. Somehow this one has left me stumped though, perhaps due to it being a god awful hack that nobody would even consider in the first place.
You need to use backticks when referring to column names which have spaces in them. So your first query from the loop is outputting as this:
UPDATE users SET Example Qualification 3='1' WHERE username='Admin2'
But it should be this:
UPDATE users SET `Example Qualification 3`='1' WHERE username='Admin2'
Change your PHP code to this:
$sql = 'UPDATE users SET `'; // I added an opening backtick around the column name
$sql .= '$qualname`'; // I added a closing backtick around the column name
$sql .= '=\'$qualbool\' WHERE username=\'$profilename\'';
Example Qualification 3 : Is that the name of your Mysql Column name ?
You shouldnt use spaces nor upper / lower case in your columnname.
Prefere : example_qualification_3
EDIT :
To get column name and Comment
SHOW FULL COLUMNS FROM users
i have a row in my database with name "active_sizes" and i want filter my website items by size, for this, i use LIKE Condition in php :
AND active_sizes LIKE '%" . $_GET['size'] . "%'
but by using this code i have problem
for example when $_GET['size']=7.0 this code shows items that active_sizes=17.0
my active_sizes value looks like 17.0,5.0,6.5,7.5,,
thanks
Using comma-separated values in a single field in a database is indicative of bad design. You should normalize things, and have a seperate "item_sizes" table. As it stands now, you need a VERY ugly where clause to handle such sub-string mismatches:
$s = (intval)$_GET['size'];
... WHERE (active_sizes = $s) // the only value in the field
OR (active_sizes LIKE '$s%,') // at the beginning of the field
OR (active_sizes LIKE '%,$s,%') // in the middle of the field
OR (active_sizes LIKE '%,$s') // at the end of the field
Or, if you normalized things properly and had these individual values in their own child table:
WHERE (active_sizes_child.size = $s)
I know which one I'd choose to go with...
You don't state which DB you're using, but if you're in MySQL, you can temporarily accomplish the same thing with
WHERE find_in_set($s, active_sizes)
at the cost of losing portability. Relevant docs here: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
You Have % signs around your $_GET value. Combined with LIKE, this means that any string that simply contains your get value will be retuned. If you want an exact match, use the = operator instead, without the percentage signs.
This will solve your immediate issue:
AND active_sizes LIKE '" . mysql_real_escape_string($_GET['size']) . "%'
If you are using the database other than MySQL, use corresponding escape function. Never trust input data.
Besides, I'd suggest using numeric field (DECIMAL or NUMERIC) for active_sizes field. This will accelerate your queries, will let you consume less memory, create queries like active_sizes BETWEEN 16.5 AND 17.5, and generally this is more correct data type for a shoe size.
I have a script:
$friendnotes = mysql_query("SELECT nid,user,subject,message FROM friendnote
WHERE tousers LIKE '%$userinfo[username]%' ");
And the content in the "tousers" table of the database:
Test
Example
User
That script appears to be working well
However, if there is a user called "Test2", it would also display content that has "Test2" in the database where $userinfo[username] is just "Test"
Is there any way to fix that problem? For example (this is just an example, I don't mind if you give another way) make it so that it searches whole lines?
EDIT: I don't think anyone understands, the "tousers" table contains multiple values (seperated by line) not just one, I want it to search each LINE (or anything that works similiar), not row
The condition
tousers LIKE '%Test%'
means that touser contains "Test" at some point, so it is true for "Test","MyTest","Test3","MyTest3", and so on.
If you want only to match the current user, try
... WHERE tousers = '$userinfo[username]'
EDIT If you really want to store multiple names in one column (separated by newlines), you could use a REGEXP pattern like
WHERE tousers REGEXP '(^|\\n)($userinfo[username])($|\\n)'
Be aware to make sure that $userinfo[username] does not contain any regular-expression-like characters ('$', '^', '|', '(', etc.). Also (as mentioned in the comments above) this solution is suboptimal in terms of security/performance/etc: It would be better to model an 1:n-Relationship between the friendnote table and some friendnotes_user table ...
Ok, so it sounds like the tousers field can contain values like 'stuff test option whatever' and 'foo test2 something blah blah', and you want to match the first but not the second. In that case, you need to include the delimiters around your search term. Assuming the search term will always have a space before and either a space or comma after it, you could do something like:
... WHERE tousers LIKE '%[ ]$userinfo[username][ ,]%'
This will encounter problems, however, if your search term can occur at the beginning of the field (no space character before it) or at the end of the field (no delimiter after it). In that case, you might need to have multiple LIKE clauses.
This will work if you remove the % signs, which are what allow for pattern matching.
$friendnotes = mysql_query("SELECT nid,user,subject,message FROM friendnote
WHERE tousers LIKE '$userinfo[username]' ");
But the consensus seems to be that using equals will be faster. See https://stackoverflow.com/questions/543580/equals-vs-like.
So in that case, change to
$friendnotes = mysql_query("SELECT nid,user,subject,message FROM friendnote
WHERE tousers = '$userinfo[username]' ");
Edit - regarding your edit, that is not a really good design. If a user can have multiple "tousers" (ie a one-to-many relationship), that should be represented as a separate table tousers, where each row represents one "touser" and has a foreign key on the user id to match it with the friendnote table. But if you absolutely can't change your design, you might want to match like this:
WHERE tousers LIKE '%$userinfo[username]\n%' ");
ensuring that there is a line break immediately following the username.
From what I understand, you should just use strict comparison:
where tousers = 'whatever'
That is because tousers like %whatever% matches any row, in which the tousers field has 'whatever' anywhere in its content, so it matches 'whatever', '123whatever', 'whatever321' and '123whatever321'. I hope you get the idea.
So you only want to search for exact name matches? If so, just use an = and remove the % wildcards:
$friendnotes = mysql_query("SELECT nid,user,subject,message FROM friendnote
WHERE tousers = '$userinfo[username]' ");
This is a perfect usage case for the MySQL REGEXP operator.