I have a database table with the following structure. id column is added later. So all id cells are empty.
id | song | album | artist
-----------------------------
| song1 | alb1 | art1
| song2 | alb2 | art2
| song3 | alb3 | art3
| song4 | alb4 | art4
| song5 | alb5 | art5
I have an array which holds the id values for the table. I'll be updating the table (the id column) with the values in the array. For example:
$array = [
"C45Rm3fLGn",
"ocIik81up2",
"IcuSn9T77y",
"tJv7AbF53r",
"a9eZ6xYM5Y",
];
These items are unique random strings.
How should I proceed? I'm thinking about iterating the array and using UPDATE on each item.
$array = [
"C45Rm3fLGn",
"ocIik81up2",
"IcuSn9T77y",
"tJv7AbF53r",
"a9eZ6xYM5Y",
];
$rows = $mysqli->query("SELECT * FROM songs")->fetch_all(MYSQLI_ASSOC);
for ($i = 0; $i < count($array); $i++) {
$row = $rows[$i];
$id = $array[$i];
$mysqli->query("UPDATE songs SET id = '$id' WHERE song = '{$row["song"]}' AND artist = '{$row["artist"]}'");
}
Is there a more preferable way?
UPDATE: I do not use auto increment and the id column didn't exist at the time of table was created. Now, I've added an id column. There are 300+ records. IDs of the records are unique random strings. Before I add another record to the database, every record needs to have a unique random string for its id, so that when I insert a new record, I can create a random string and check if it's unique or not by comparing it to the ids in the table.
At this stage, I just need to update the id column using an array. Array items are irrelevant.
Prepared statements are designed to be prepared once and executed many times, with a minimum of overhead. Using them is also an absolute necessity if the data you're inserting is user-generated.
It's been a long time since I've done anything with MySQLi (I strongly recommend looking at PDO for much simpler code) but this should work:
$array = [
"C45Rm3fLGn",
"ocIik81up2",
"IcuSn9T77y",
"tJv7AbF53r",
"a9eZ6xYM5Y",
];
$rows = $mysqli->query("SELECT * FROM songs")->fetch_all(MYSQLI_ASSOC);
$stmt = $mysqli->prepare("UPDATE songs SET id=? WHERE song=? AND artist=?");
foreach ($array as $i=>$id) {
$row = $rows[$i];
$stmt->bind_param("sss", $id, $row["song"], $row["artist"]);
$stmt->execute();
}
I would also recommend building your array such that it references the columns you're renaming. You're relying on both the database and the array being in the same order, which may not always be the case.
Please try this query:
UPDATE `myTable` SET `id`= CONCAT(item-name, "-id");
Or you can set a counter like this:
UPDATE `myTable`, (SELECT #i := 0) c SET `id`= CONCAT(item-name, "-id-", #i:=#i+1)
I hope this will help you.
Related
I have a two columns in database:- copy (which is array) and bookid. My code is;
$query = mysqli_query($db, "select copy from book_outward WHERE bookid like 'B1'");
while ($row = mysqli_fetch_array($query)) {
$copyid = $row['copy'];
}
Database shows like this
+----------------+
| id copy bookid |
+----------------+
| 1 1 B1 |
| 2 2,3 B1 |
| 3 4 B1 |
| 4 2 B2 |
+----------------+
but it stores only last values which was entered in 'B1'. I also tried
$copyid[] = $row['copy'];
but in this case I have to change array keys manually every time.
My aim is to insert copy into column bookid='B1' and before it has to make sure that only UNIQUE values can be stored in database for B1.
HTML :-
<input type="text" name="bookid" />
<input type="text" name="copies[]" />
PHP code for inserting:-
$book_id = $_POST['bookid'];
$copies = implode(',',$_POST['copies']);
$result = mysqli_query($db, "insert into book_outward(bookid,copy) values ('$book_id','$copies')");
As some of the comments mention it it not the best way to to it but it is possible.
You can obtain all the copyid data by:
$query = mysqli_query($db, "select copy from book_outward WHERE bookid like 'B1'");
$copyid = "";
while ($row = mysqli_fetch_array($query)) {
$copyid .= $row['copy'] . ",";
}
$copyidsFromDB = explode(",",rtrim($copyid , ','));
After that you can check if what you got in the request are in there using array_intersect:
$copies = $_POST['copies']
// if not an array use: $copies = explode(",", $_POST['copies'])
if (count(array_intersect($copies, $copyidsFromDB) == 0)
// insert to DB
Solved by myself by adding one line only
`$copies2 = explode(",",rtrim($copies , ','));`
before array_intersect Thanks code helps greatly.
So, sounds to me like the issue is the original data DB schema has some issues.
A sql-like DB is not a great place to put 'array' style value. It already has a mechanism for doing this: a link table.
That'd save you the trouble of having to manually shuffle around your primary keys in this table. It's way easier to check and validate.
If you HAVE to do this via php code, for example you don't have SQL access, like in a controlled build environment, you should take advantage of 'string keys' to on your $copyid, (hint rename to $copyidmap) to group together like pieces of data and preserve key relationships.
so the following would be unique:
map->{bookId}->{copyid}->{id} // Where id is that primary table id. Obviously, validate and do your undefined array assignments.
I'm having an issue querying multiple values from rows that have a certain value. I use the SQL code below to grab column "group_id"'s values if the "id" equals 999. In the "xx_groupmap" table, the id 999 shows up three times with different values. Below is my table.
table xx_groupmap
-------------------
id | group_id
-------------------
999 | 2
999 | 7
999 | 8
Below is the code I use
$db = JFactory::getDbo();
$query = "SELECT group_id FROM xx_groupmap WHERE id = '999'";
$db->setQuery($query);
$results = $db->loadObjectList();
foreach ($results as $t) {
}
So in the end when I want to return the three values of id 999 I use this code
echo $t->group_id;
but it only outputs one number. How do I build an array with the three values from id 999?
Thats because, when you are in the foreach, $t is always updated, and you will get tha last $t only. Put them into an array.
$ids = array();
foreach ($results as $t) {
$ids[] = $t->group_id;
}
var_dump($ids);
I need to figure out a way to prepare an insert statement in PHP for a SQL db and I'm having trouble comprehending the logic. The insert statement will be from data I'm receiving in JSON. The JSON contains questions and answers. The table I'm inserting them into is the problem. On the front end (website) the table has column names that represent the questions and it look like this.
Date | Address | City | Zip
Now the problem is in the database these names don't carry over. The column names are just column1 column 2 etc. So it looks like this
Column1 | Column2 | Column3 | Column4
Another thing - when each table like this is created it will have different values so I can't hard code the relationship. Also these tables are created from importing an excel spreadsheet from the front end (website). So I came up with a plan to duplicate row 1 & 2 of the spreadsheet so that now when you import them the database looks like this
id | Column1 | Column2 | Column3 | Column4
1 | Date | Address | City | Zip
So now I have some reference to the values that will need to be inserted. Now the next steps involved will be.
Query for column name based on the data in row 1 OR change the column name to the data in row 1.
Insert data into the correct columns based on the query
So in summary I cannot insert the answers into the correct column representing the question without the proper information. I personally think changing the column names in PHP would be the better option. However I'm pretty new to PHP and SQL so I don't even know if this is possible. Any help is appreciated
EDIT
to give a slightly better understanding of the problem I am posting the PHP I currently have.
$json = safe($_POST['assessment']);
/*
$json =
'{
"info":
[
"Date: 6-22-13",
"Phone #: (555) 555-5555",
"Address: 304 N. SCOTTSDALE RD.",
"City: SCOTTSDALE",
"Zip: 85251",
"State: AZ"
]
}';
*/
$data = json_decode($json,true);
$collection = array();
foreach($data['info'] as $piece) {
$info = explode(':', $piece);
$collection[] = array('question' => $info[0], 'answer' => $info[1]);
}
echo '<pre>'; print_r($collection); echo '</pre>'
The following should create an associative array that maps the names of columns to the column numbers in the database schema:
$stmt = $db->prepare('select Column1, Column2, Column3, ... from table where id = 1');
$result = $stmt->execute();
$data = $result->fetch(PDO::FETCH_ASSOC);
$col_map = array_flip($data);
You can then use this when preparing future queries of the database.
If you don't know how many columns you could have, you could do this:
$stmt = $db->prepare('select * from table where id = 1');
$result = $stmt->execute();
$data = $result->fetch(PDO::FETCH_ASSOC);
unset($data['id']); // Remove the `id` column, which doesn't conform to the ColumnN pattern
$col_map = array_flip($data);
If I have a table like this:
+-------------+-------------+
| Field | Type |
+-------------+-------------+
| document | varchar(35) |
| section | int(11) |
| selection | int(11) |
| status | varchar(35) |
+-------------+-------------+
And I have an array in PHP. Let's call it $choices[]. The column selection coresponds to an array index for the choices array. If I add an element or elements to the $choices array then I need to update the database. I'd be operating in a loop where $document and $section are also set. I don't want to assume that there are no missing rows in the middle of my numbering. What's the most efficient way to check for (document,section,selection) for each element in $choices, create any that does not exist, and set its status to "new"?
Do I have to do this as a loop, or is there a way to do this in one query?
This is completely untested, but this is basically how I'd do it if I didn't ask for help. I guessed someone might have a MUCH better solution than me.
foreach($documents as $document)
{
foreach($sections as $section)
{
$choices=$master_array[$document][$section];
$ch_count=count($choices);
$counter=0;
while($counter < $ch_count-1)
{
$query="SELECT status FROM mytable WHERE document='$document' AND section='$section' AND selection='$counter'";
$result = mysql_query($query);
if(mysql_num_rows($result)==0)
{
$query="INSERT INTO mytable VALUES('$document','$section','$counter','new')";
$result = mysql_query($query);
}
$counter++;
}
}
}
If everything is going to be updated with "new", then this can be achieved somewhat easily.
Examine the following code:
<?
$setStr = "";
foreach($choices as $column)
{
$setStr .= $column . "=" . "'new', ";
}
$sqlCommand = "UPDATE table SET ".substr($setStr,'',-2)." WHERE pick_a_row_here;";
echo $sqlCommand;
?>
For the ones that do not exist, try configuring it so their values are default to false when unspecified. Of course an INSERT statement can easily be adapted from my above UPDATE statement.
Let me know what you think. If you have questions or comments, I'll do my best to answer them.
I ended up using a loop to contatenate together a large query string that looked something like this, except much larger:
INSERT IGNORE INTO mytable VALUES
('doc1','1','0','New'),
('doc1','1','1','New'),
('doc1','1','2','New'),
('doc1','1','3','New'),
('doc1','2','0','New'),
('doc1','2','1','New'),
('doc1','2','2','New'),
('doc1','2','3','New'),
('doc1','3','0','New'),
('doc1','3','1','New'),
('doc1','3','2','New')
And it works. Whether or not its the best, I don't know but at least I'm not sending hundreds of queries to the DB.
I have a table called "profiles". There was a column in this table called "user_id" which I have changed the name to "username" and the type from INT(11) to Varchar(255) . However the contents of this column are still numeric ids.
These ids correspond to another table called "users". That table has fields called "user_id" and "username". For each row on the "profiles" table I need to first check to see what the username field has for the id and do a look up on the users table to get the username that correcponds to that id and then update the profile table's username value for with the proper username.
Profiles table:
username | blah blah...
------------------------
1 | ...
Users table:
user_id | username
------------------------
1 | Joe
I need the value for the username field on the profiles table to be updated to "Joe".
I came up with this php script but it stops working after updating just 4 records for some reason:
$sql = 'SELECT username FROM profiles';
$query = mysql_query($sql);
while($row = mysql_fetch_assoc($query)) {
$id = $row['username'];
$sql = 'SELECT username FROM users WHERE user_id = '. $id;
$query = mysql_query($sql);
while($row = mysql_fetch_assoc($query)) {
$sql = "UPDATE profiles SET username = '".$row['username']."' WHERE username = $id";
$query = mysql_query($sql);
if(!$query) {
echo 'error!';
}
}
}
My script isn't all that efficient to begin with, although that's not that big an issue since the table has just 50k records. Anyway what would be a way to do this directly from mysql?
You are manipulating the $row variable inside the first loop. Obviously it does not work. Try giving the variable in inner loop a different name.
And not only that almost all the variables you are using, outside the first loop, you are using the same names inside the inner loop.
Also coming to db schema I would prefer ids to be foreign keys not usernames because querying using ids would be faster than with columns of type varchar.
One more suggestion is that there is no need to use
while($row = mysql_fetch_assoc($query))
because there would be only one row
As Napster said you're overwriting your $query, and $row variables. That should fix your immediate issue.
Additionally, a query inside of a while loop, inside of a while loop is absolutely terrible. No offense intended! We all have to start somewhere. But I would strongly look into how you can rewrite this with a JOIN just so you have something in your toolbelt for that next time.
Hope that helps!
I think relationship between your tables is wrong, you should have a foreign key in profiles table that links to user_id in the users table, then if you change something like Joe to Michael, its corresponding record in profiles table will be updated.
Profiles table:
user_id | blah blah...
------------------------
1 | ...
Users table:
user_id | username
------------------------
1 | Joe
You can do this in one query
UPDATE profiles t1
INNER JOIN users t2 ON t1.username=t2.user_id
SET t1.username=t2.username
Why you would want to do this is another question.