Ok, here's an easy one:
I have a table in MySQL where I keep some country names (inserted by the user). The "problem" is that some of the users inserted the country name having no first capital letter.
A need a script (query+PHP) that selects all the values from 1 column inside the table, and apply a PHP script that makes the first letter of every word a capital letter, and the rest in small letter.
Example:
Before edit:
Name oNe
cOUNTRY
VaLue
value
After edit:
Name One
Country
Value
Value
I want to know two things:
->easiest way to edit a value inside a mySQL table
->easiest PHP way to capitalize the first letter of every word (space separated) inside a script
Thanks!
You can use this function:
DELIMITER $$
DROP FUNCTION IF EXISTS `ICap`$$
CREATE FUNCTION `ICap`(mystring varchar(1000))
RETURNS VARCHAR(1000)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE myc, pc CHAR(1);
DECLARE myoutstring VARCHAR(1000) DEFAULT LOWER(mystring);
WHILE i <= CHAR_LENGTH(mystring) DO
SET myc = SUBSTRING(mystring, i, 1);
SET pc = CASE WHEN i = 1 THEN ' ' ELSE SUBSTRING(mystring, i - 1, 1) END;
IF pc IN (' ', '&', '''', '_', '?', ';', ':', '!', ',', '-', '/', '(', '.') THEN
SET myoutstring = INSERT(myoutstring, i, 1, UPPER(myc));
END IF;
SET i = i + 1;
END WHILE;
RETURN myoutstring;
END$$
DELIMITER ;
After that, you can retrieve results like this:
SELECT
ICap(name)
FROM
MyTable
or just update all the rows:
UPDATE
MyTable
SET
name = ICap(name)
To fix the database with only one sql statement use this:
UPDATE country_table SET country_name = CONCAT(UCASE(MID(country_name,1,1)),MID(LOWER(country_name),2));
This will uppercase the first letter of each country name and lowercase the rest. All without needing any PHP at all.
->The easiest way to edit a value inside a mySQL table
UPDATE TABLE SET COL="NEW VALUE" where COL="OLD VALUE";
Be careful, it will replace all line wher COL is equal to OLd VALUE
->easiest PHP way to capitalize the first letter of every word (space separated) inside a script
There's a function for that : http://php.net/manual/en/function.ucwords.php
To Edit the values in in the database just run a Update Query (I don't know how your table is designed) from php -- http://www.w3schools.com/php/php_mysql_intro.asp.
To Capitalize the first character of every word you can use ucwords.
You can do it all in mysql if you want:
SELECT CONCAT(UPPER(SUBSTRING(CountryName, 1, 1)), LOWER(SUBSTRING(CountryName FROM 2))) from countries AS properCountryname;
The resultset returned would be your CountryName field with uppercased first letter.
You coud even do the update in one sql query, if you wanted.
If you really want php to do the job, something like this:
<?php
set_time_limit(0);
$cnt=0;
$con=mysql_connect('localhost','root','');
mysql_select_db('fakeDB',$con);
$query="SELECT `name`,id FROM countries";
$result=mysql_query($query);
while ($row=mysql_fetch_array($result))
{
$name= $row["name"];
$key = $row["id"];
$field = strtolower($name);
$array=explode(" ",$name);
for ($i=0;$i<count($array);$i++)
{
$array[$i] = ucfirst($array[$i]);
}
$field = implode(" ",$array);
$query2 = "UPDATE countries SET `name`='$name' where id=$key";
mysql_query($query2);
$cnt++;
}
echo $cnt." Records updated";
?>
Just a quick untested thingie but it should give you an idea.
Related
I have a TXT file with no punctuation between them. I would like to shred this file by the table column widths in the database and save it.
Let me tell you this step by step…
I’m creating a table in the database with my tabloolustur.php page. The column numbers and column widths of the tables I create will not be the same.
There are no punctuation marks between the TXT file data. First, I want to split the TXT file rows by column width.
$result = $baglanti->prepare("SHOW COLUMNS FROM customers where Field NOT IN('id')");
$result->execute();
$colcount = $result->columnCount()-1;
$columLen = array();
foreach($result as $key => $col){
preg_match('/\d+/', $col['Type'], $len);
$len = (isset($len[0]))? $len[0] : '';
$fieldname = $col['Field'];
$columLen[$fieldname] = $len;
}
For this, I get the number of columns and column widths with the code.
Then, I separate the data with commas with the following function.
function txtBol($metin, $genislik){
$parcala=array();
foreach ($genislik as $sutunadi => $lenght)
{
$parcala[$sutunadi] = substr($metin, 0, $lenght);
$metin = substr($metin, $lenght);
}
return $parcala;
}
I also get column names with the following code. (ps: to use in a query)
$KolAdi = $baglanti->query("SHOW COLUMNS FROM customers where Field NOT IN('id')");
$KolAdi->execute();
$colonAdi= $KolAdi->fetchAll(PDO::FETCH_COLUMN);
$colonAdi=implode(',', $colonAdi);
It prints the data i split correctly when printing it to the screen. So far, so good. But I can’t create the right query with PDO. How should I create the query? (ps: Table column names and column widths are not the same. There will be different numbers and width columns for each table)
I would appreciate it if you could help. I proceeded by implementing some solutions from your site.
Table:
id
name
cev1
cev2
cev3
1
MARTIN EDEN
AAAAAA
BBBBB
CCCC
txt:
MARTIN EDEN........AAAAAABBBBBDDDD
Assuming a valid PDO connection in $PDO, you can do the whole job like this.
It reads the column data once and uses that to create a query to prepare and a regular expression to extract the data.
$table = 'customer';
$txtFile = 'cust.txt';
// No need to prepare this since there's no untrusted data here.
$result = $pdo->query("show columns from `$table` where Field <> 'id'");
// Get column names and widths in arrays
while($columns = $result->fetch(PDO::FETCH_ASSOC)) {
$colNames[] = $columns['Field'];
preg_match('/\d+/', $columns['Type'], $len);
$colLengths[] = $len[0]??'';
}
// Create regex to extract data from lines:
// Looks like this: /(.{20})(.{10})(.{5})/
$regex = '/(.{'.implode('})(.{',$colLengths).'})/u';
// Create skeleton query with table name and field names and placeholders
// Looks like this: INSERT customer (name,addr1,postcode) VALUES (?,?,?)
$query = "INSERT $table (`".implode('`,`', $colNames).'`) VALUES ('.str_repeat('?,', count($colNames)-1).'?)';
// Read text file
if ($fileData = file($txtFile)) {
// Prepare the query only once
$stmt = $pdo->prepare($query);
foreach ($fileData as $row) {
// Get the data using the regex from above
preg_match($regex, $row, $rowData);
// Remove the first row of the regex matches - see PHP manual for why
array_shift($rowData);
// Now execute the prepared query using the data extracted by the regex.
$stmt->execute($rowData);
}
}
Note that this codes assumes that the table consists of a series of contiguous columns from which it can extract column widths, and no other columns except id, which it ignores. If your actual table structure is different you'll need to modify the SHOW COLUMNS query to omit those columns, or modify the code that extracts the column data to extract only the relevant columns.
{Edit]
Updated the code to include /u UTF-8 modifier on the regex, and to wrap the column names in the INSERT query in back ticks.
you can create a table like this and you don't need to check a number of fields by rows
let me know if this useful
CREATE TABLE new_table (
id INT NOT NULL AUTO_INCREMENT,
row_id INT NULL DEFAULT 0,
row_field_name VARCHAR(50) NULL DEFAULT NULL COMMENT 'Index of ',
row_value VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (id));
I have multiple ids separated by + in one field of a row in a table
Like : (123+21654+412+12387)
I need Only EXACT MATCHES, (e.g.: only "123" and not "123 & 12387")
My code is like this:
$var = $value['id'];
$result = mysqli_query($this->dbh, "SELECT id FROM table
WHERE id REGEXP '[[:<:]]$var[[:>:]]' ");
I have a problem with using a variable in REGEXP.
in case of :
$result = mysqli_query($this->dbh, "Select id FROM table
WHERE id REGEXP '^$id|[\+]$id' ");
it works, but it does not return only exact matches
PHP tip: "Interpolation" works these ways:
"...$var[...]..." treats that as an array lookup for $var[...].
Without [, $var is assumed to be a scalar.
"...{$var}[...]..." is what you need
This last example has braces {} to tell PHP to evaluate what is inside without being concerned about what follows. More common usage:
$var = 'abc';
// I want to generate "abc123"
$bad = "$var123"; // looks for variable 'var123'
$good = "{$var}123; // correctly yields "abc123"
Your second attempt can be fixed thus:
REGEXP '(^|\+)$id(\+|$)'
meaning:
At the beginning or after a +,
Find $id (after interpolating),
And stop with a + or the end of the string.
I'll go with :
$sql = "SELECT id FROM table WHERE id='123' OR id LIKE '123+%' OR id LIKE '%+123' OR id LIKE '%+123+%'";
The first condition will apply if you only have the value, the second if the field starts with the value, the third if the field ends with the value and the fourth if the value is in the middle of the field.
I want to make a product search engine where the user types in a product code and it will bring back the result, this is easy.
But, I want to be able to compensate for numbers that look like letters and vice versa.
E.g a user types 6O12l, but the product code is actually 60121.
What do I need to put in the SQL query to bring back all products with 6O12l and/or 60121?
So far I have this which isn't working, it keeps bringing back the same result everytime no matter what I type in:
$searchString = $_POST['query'] ;
$searchString = preg_replace('#\W#', '', $searchString);
$firstLetter = substr($searchString, 0, 1) ;
include("db.php") ;
$result = $dbh->prepare("SELECT productCode
FROM products
WHERE productCodeREGEXP '6[O0]12[1l]'
AND productCode LIKE '$firstLetter%'") ;
$result->execute() ;
while($row = $result->fetch(PDO::FETCH_ASSOC)) {
echo $row['productCode'].'<br />' ;
}
I have managed to get it working, but I have encountered a new problem.
I'm using str_replace to substitute the letters for numbers and viceversa in the users query string, but it will only work for one or the other, not both:
$qString = str_replace(array('o', 'l', '0', '1'), array('[O0]', '[1l]', '[O0]', '[1l]'), $searchString) ;
Which gives me a mangled output of e.g. A[[1l]l]BC
Instead of A[1l]BC
Do you have product codes with letters? You can translate the query string to all numbers before you run the query. That's the easiest thing to do, and will be much faster than testing for both.
You can't search the database efficiently with regular expressions. However, you can transform your data for storage in a normalised form, and search using a normalised query string e.g. all O's to zeros, I and l's to ones and so on.
Use this:
SELECT * from products
where code REGEXP '6[O0]12[1l]'
I solved it :D
For reference, I found this function on PHP.net:
function search_replace($s,$r,$sql)
{ $e = '/('.implode('|',array_map('preg_quote', $s)).')/';
$r = array_combine($s,$r);
return preg_replace_callback($e, function($v) use ($s,$r) { return $r[$v[1]]; },$sql);
}
Another option
// regex expresssion
// str_replace goes in order, first change letters to numbers, then change to the regex
// 6012ol becomes 6[0O][1l]2[0O][1l]
$regexString = str_replace(array('o', 'l', '0', '1'), array('0', '1', '[0O]', '[1l]'), $searchString);
// like expression, allows the database to make the initial filter, _ is the single character match
// 6012ol becomes 6__2__
$likeString = str_replace(array('o', 'l', '0', '1'), '_'), $searchString);
$filt1 = "(productCode LIKE '$likeString%')"; // last % allows for partial matches
$filt2 = "(productCode REGEXP '$regexString')";
// now query, with the like filter first
$dbh->prepare("SELECT productCode
FROM products
WHERE $filt1 AND $filt2
") ;
My current MSSQL table has a "phone" column which is a varchar. Unfortunately, the phone numbers that are already in the database are not in standard format. For example, 888-888-8888 OR 888/888/8888 OR (888)8888888 OR 8888888888.
I want to get all the rows that are equivalent to 88888888, i.e it should match with 888-888-8888, (888)888888 etc.
I have tried using REPLACE() but there are certain rows where entries have other alphabetic characters like "e", "ex", "ext", etc. So I would like to replace all non-numeric characters.
What would be the best way to get the "matching" rows using MSSQL query?
You can try this function (MS SQL Server):
CREATE FUNCTION uf_RemoveNotNumbers (#str varchar(max))
RETURNS varchar(max)
AS
BEGIN
WHILE #str LIKE '%[^0-9]%'
SET #str=replace(#str, substring(#str, patindex('%[^0-9]%',#str),1),'');
RETURN #str
END
GO
DECLARE #str varchar(max);
SET #str = 'q56--89+9*67qweresr';
select dbo.uf_RemoveNotNumbers (#str)
A simple version using MySQL:
SELECT * FROM `phones` WHERE `phone` LIKE '%8%8%8%8%8%8%8%8%8%8%'
Using PHP:
// Get all your table rows into $rows using SELECT ..
foreach ($rows as $row) {
$row['phone'] = preg_replace('/\D/', '', $row['phone'];
// Save the row using UPDATE ..
}
The regular expression \D matches any non-numeric character. See php.net/preg_replace for more information.
If you just want to find a row that matches "8888888888", then you could use:
if (preg_match('/\D*8\D*8\D*8\D*8\D*8\D*8\D*8\D*8\D*8\D*8\D*/', $row['phone'])) {
..
}
Which could simplify/abstract to:
$match = '8888888888';
if (preg_match('/' . preg_replace('/(\d)/', '\D*$1', $match) . '\D*/', $row['phone'])) {
..
}
Why not write a php script that would do it for you?
ex. get all rows -> replace -> update
heres the query that might work on MSSQL.
create FUNCTION dbo.Only_Numbers
(
#string VARCHAR(8000)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #IncorrectCharLoc SMALLINT
SET #IncorrectCharLoc = PATINDEX('%[^0-9]%', #string)
WHILE #IncorrectCharLoc > 0
BEGIN
SET #string = STUFF(#string, #IncorrectCharLoc, 1, '')
SET #IncorrectCharLoc = PATINDEX('%[^0-9]%', #string)
END
SET #string = #string
Return #string
END
GO
select dbo.Only_Numbers('888*88-88/2')
You can try this code:
$query="select * from tablename";
$result=mysql_query($query);
while($row=mysql_fetch_array($result))
{
$str = preg_replace('[\D]', '', $row['phone']);
}
There's a mysql database that stores ids and names, when users are creating names with a form they can create existent names since unique ids are the ids such as:
d49f2c32f9107c87c7bb7b44f1c8f297 name
2fa9c810fbe082900975f827e8ed9408 name
what i want to do is saving the second "name" -> "name(1)" when inserting into database.
So far what I've got is this as the idea
lets say the name entered is 'name'
$input = 'name';
select the name we want to check from mysql database
mysql_query(SELECT * FROM `table` WHERE `name` = '$input');
if the result exists, then insert as $input.'(1)'
my question is what if name exists, and name(1) also exists, then how can i add the name(2) there...
You could return the number of people with that name in the database, then add 1 to that number.
SELECT COUNT(id) FROM table WHERE name LIKE '$input(%)');
$i = 1;
$sourceName = $name;
while( sql "SELECT COUNT(*) FROM table WHERE name = '$name'" ) {
$name = $sourceName.' ('.$i.')';
$i++;
}
At this point you have the final $name (with $i counting the iteration)
Something like this should do the trick:
SELECT * FROM table WHERE name = '$input' OR name LIKE '$input(%)'
Note that for this to work, you'd need to escape any percent signs in $input in the LIKE clause, otherwise they'll be treated as wildcards.
Use a regex that checks for integers between two parentheses at the end of the string. If there exists an integer, add 1 to it.
You could also attempt to do it the other way around, make name field unique and try to input it in a while loop, if it fails add ($i) and do $i++ every iteration.
//edit:
The problem with using solutions that do a like comparison is that you will get false positives, for instance $hi% will also count hippie. Which gives you unnecessary (1) additions!