MySQL query REPLACE field name with PHP function - php

Within a MySQL query, is it possible to put a PHP function around a field name in order to change/replace its value?
SELECT * FROM my_table WHERE url_title(field_name) = '$variable'
The reason for asking is that the '$variable' in my URL which the query will use is an edited version (using Codeigniter's url_title function) of its true value eg. $variable = 'dangelo' whereas its true value in field name is "D'Angelo".

You can implement the url_title function as a MySQL stored procedure, which would require translating the PHP code of that function to a MySQL stored procedure.
Note that the performance would not be great due to having to call this function for every row on each query.
The more typical solution is to have another field for the slug, pre-generate the values for each article's slug. On the query, you would compare $variable to the new field.

Yes it's possible. But not at all recommended because it wouldn't be able to make use of the index. Create another column with the actual value you want to find and add an index to that column.

Related

MySQL select query finds a result that shouldn't be found in PDO

So, for a school assignment I have to make a website. This website must contain a functionality that gets articles out of a database.
I can, for example, show article 1 with domain.com/content/article/1/.
However, when I use a URL like this domain.com/content/article/2aadd/ it still shows article 2.
Even ../10aadd/ shows article 10.
If I try to request an article that doesn't exist with like ../11aadd (article 11 doesn't exist) it will show an error that it can't find the article, like it should.
I use URL rewriting so a URL like this domain.com/content/article/1/ is rewritten as domain.com/index.php?c=content&a=article&arg=1
I use a database class, every select query is sent to a select-query method. It accepts the following parameters:
$q - the query
$params - an array with parameters for the query
$fetch - the fetching mode
The following parameters are sent in order to show an article:
select title,content from PHP2b_OOP_EIND_Articles where id=:id and enabled=1
array("id"=>$_GET["arg"])
assoc
In every call of this method a new statement is being prepared and executed with the $params array as parameter.
I've dumped out the $params array and it does show the entire string (e.g. 10aadd).
I've tried it without the clean URL.
I've tried to look it up but I couldn't find anything.
What could be the cause of this?
I suspect your MySQL table's id column is defined as an integer data type.
You're experiencing a peculiarity of MySQL when it coerces a string data type to an integer.
select CAST('10aaadd' AS INT)
gives back the value 10, strangely enough.
Your query, after variable substitution, says WHERE id = '10aaadd'.
Because MySQL implicitly casts that string to an int, it finds the row with the id value of 10.
Weird, huh?
If you expect only integers in a $_GET or $_POST parameter, it's a good idea to check for that and throw an error if the values you receive don't match expectations. PHP's is_numeric() function can do that for you.

Concatenating original value with query value in MySQL

I am trying to something in MySQL that I do in JavaScript/PHP all the time. I need to concatenate the value of a field in MySQL with a value that is passed into a query from PHP. For example, let's say I have a field called favourites with a value of 27 and I have this query:
UPDATE useraccs SET favourites = favourites + ',30' WHERE id='10'
My desired new value for favourites would be 27,30, but I'm getting 57, where clearly SQL is adding them numerically. I have set the data type for this column as TEXT and was hoping that would force SQL to treat it as a string all the time, but that doesn't seem to be the case.
In my research I read about the CONCAT() function, and I tried this:
UPDATE useraccs SET favourites = CONCAT(favourites,',30') WHERE id='10'
That results in a failed query. The logic feels right but that is obviously not how that function is meant to be used.
I acknowledge that in theory, I could just grab the original value of favourites and concatenate it with the new value in the PHP itself and then send it to MySQL, but I feel like there MUST be a way to do this in one query...if I'm wrong about that so be it, but I'm sure there must be a way.
Use the following to create '27,30':
CONVERT(favourites,char) + ',30'

Parsing first line of csv and creating a table inside database

I am downloading new csv's each night using a cron job with PHP. Each csv is normally about the same, possibly one night within a month a field is new. I need to get the new field and append it to the database. I don't know how to get the type of the new field. I saw someone else's question with gettype() but i'm not sure if that would work or not since the data is inside a csv so wouldn't they all be strings when some need to be floats, or ints? How would I go across checking the type?
The second question, is there a way to check if there is not a name inside of a table? For instance, if they add a new field called foo52, and I have foo1 through foo51 in my database, is there a quick way to search for fields that aren't there, or would I have to use a select statement for each one and append it when it's false?
I use MySQL for my database.
Thanks for your help.
The first question on the part about getting the type is the simply try the conversion of the data itself and then seeing if the data is equivalent with a == comparison.
So,
some,data,is,123
After reading in the data you can then try the conversion to various types such as strings, ints, ect...then from that you are able to determine the type of the data.
For the second question you can get the column names by doing:
show columns from db.table_name
Then you can do a simple in_array to test if the new column name is already in the database.
EDIT:
Using array_diff can simplify the finding of the missing/new column names from the CSV.
csv_names = get_csv_column_names();
sql_names = get_sql_column_names();
new_names = array_diff( csv_names, sql_names );
I have found the parsecsv-for-php library very handy for [re|de]constructing CSV data.
For the first question: you can test if it's numeric with is_numeric(). If not, store as string. If yes, create the field as numeric in your database. If you want, you can use regex to check if it's a date or some other datatype you think is required to be stored correctly (i.e. not a a default-text)
for the second question: getting the fieldnames of a table in Postgres is done with the follwoing query
$sql = "SELECT attname FROM pg_catalog.pg_attribute
WHERE attrelid =
(SELECT c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = '$this->tableName' AND n.nspname = 'public')
AND attnum > 0
AND NOT attisdropped";
For MySQL, it should be doable with "show columns from db.table_name".
Once you have the fields, use in_array() to check if it exists already...
Note that: you'd probably need to check for all columns in your CSV if they exist already. If not: add a new colum for it. If yes, leave it as is...

retrieve last updated column in mysql

I have a MySQL query that goes as follows (using Zend_Db):
$sql = $handle->quoteInto("UPDATE board SET rank=rank+1 WHERE post_id=?", $postid);
$handle->query($sql);
(Rank isn't an auto-incrementing PK).
I would like to now retrieve the value of rank without preforming another query.
I've tried $handle->lastInsertId(); but it doesn't seem to work , since I didn't use MySQL's natural auto-incrementing method (I can't - rank is the rank of a post. I either ++ or -- it.)
Any way to do this with preforming another query? A function that will return the last changed value?
I don't believe this is possible - you'll just have to do a SELECT.
You can use the LAST_INSERT_ID function that MySQL provides to set a value and then make it available via the mysql_insert_id() C function that the $handle->lastInsertId(); relies on.
The following is an updated version of your code snippet with the LAST_INSERT_ID changes made to it:
$sql = $handle->quoteInto("UPDATE board SET rank=LAST_INSERT_ID(rank+1) WHERE post_id=?", $postid);
$handle->query($sql);
Let me know if you have any questions.
HTH,
-Dipin

PHP/MySQL - How do you determin the field names from a given query result?

Given a result set, how can I determin the actual names of the fields specified in the query (NOT their aliases).
$query = "SELECT first AS First_Name, last AS Last_Name FROM people";
$dbResult = mysql_query($query);
$fieldCount = mysql_num_fields($dbResult);
for ($i=0; $i<$fieldCount; $i++) {
// Set some values
$fieldName = mysql_field_name($dbResult, $i);
}
This example returns field names, but in this example it returns the alias "First_Name" instead of the actual field name "first".
Is it possible to get the actual field name from such a query. Particularly if I am writing a function and have no idea what query will be thrown at it.
If you are using MySQLi:
http://www.php.net/manual/en/mysqli-result.fetch-field.php
The field object has a "orgname" property.
The "classic" MySQL equivalent function doesn't report back the original column names.
Short answer: you don't.
Long answer: Once the dataset is pulled by MySQL and sent back to PHP, the only information PHP now has is the columns, or aliases if you used them. There is no way to look at a result set and determine what the original column names were. You have to switch to another DB driver like mysqli to obtain this info.
Your question doesn't make sense.
What are you going to do if you get a derived column i.e.
select column_a + column_b as order_total from orders;
are you saying you want to know that the original query was column_a + column b ??
if so, you probably need to write a query parser, or get one off the internet.
I think the implementation of that is beyond the scope of your question though :)
I'm not 100% sure about this, but I would say: there is no way.
The MySQL gives you back the result set, nothing more. It does not return the select statement nor any details about it.
So you cannot get the original field names because the server will provide you the information you asked: alias names.
If you don't mind making a second query (and your using MySQL 5 or greater) you can ask information_schema for the names.
Check out MySQL Reference for the details:
SHOW COLUMNS FROM tbl_name;
if you have access to the string of the query you could try a regular expression to parse it.
I'm no regex master but you could chop up the string by looking at the text between 'select' and 'from' then grabbing all the field names as either
field FieldAlias
or
field as FieldAlias
If you're trying to write some functionality to let you know what fields are being fetched for handling updates - the only way to do this correctly is for it to present an SQL-less interface to the code above and manage all SQL generation itself. This is called a data abstraction layer.

Categories