When I was delete record Users, the ID primary key auto increment always jumping, I want ID auto increment is sequence again, this sample
| ID | UserName |
| 1 | Budi |
| 2 | Joko |
| 3 | Amir |
when I delete users Joko, then I add new other user, the ID number is jumping
| ID | UserName |
| 1 | Budi |
| 3 | Amir |
| 4 | Faris |
while I've browsing solution, I get some solution, but doesn't work.
here I've add modified file
config/app.php
'SQLkonek' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'root',
'paassword' => ' ',
'database' => 'klinikucing',
'encoding' => 'utf8mb4',
'timezone' => ' ',
'cacheMetadata' => true
]
then I call modified above through
controller/UsersController.php
public function delete ($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$kon = ConnectionManager::get('SQLkonek');
$user = $this->Users->get($id);
$stm = $kon->execute(array(
['SET #count = 0'],
['DELETE FROM users WHERE ID = :ID'],
['UPDATE users SET users.ID = #count:= #count + 1'],
['ALTER TABLE users AUTO_INCREMENT =1']
))
->fetchAll('assoc');
If($this->Users->$stm) {
$this->Flash->success(__('Users success delete.'));
} else {
$this->Flash->error(__('User delete failed, try again.'));
}
return $this->redirect(['action' => 'index']);
}
The error message was shown
Warning (2): PDO::prepare() expects parameter 1 to be string, array given [CORE\src\Database\Driver\Mysql.php, line 138]
Warning (512): Unable to emit headers. Headers sent in file=C:\xampp\htdocs\klinikucing\vendor\cakephp\cakephp\src\Error\Debugger.php line=853 [CORE\src\Http\ResponseEmitter.php, line 48]
Warning (2): Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\klinikucing\vendor\cakephp\cakephp\src\Error\Debugger.php:853) [CORE\src\Http\ResponseEmitter.php, line 148
Warning (2): Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\klinikucing\vendor\cakephp\cakephp\src\Error\Debugger.php:853) [CORE\src\Http\ResponseEmitter.php, line 181]
Argument 1 passed to Cake\Database\Statement\PDOStatement::__construct() must be an instance of PDOStatement or null, boolean given, called in C:\xampp\htdocs\klinikucing\vendor\cakephp\cakephp\src\Database\Driver\Mysql.php on line 139
Error in: ROOT\vendor\cakephp\cakephp\src\Database\Statement\PDOStatement.php, line 33
My CakePHP version is 3.7.2
I hopefull that someone can help me, thanx
Don't renumber. Accept there will be gaps in AI due to deleting an other cause (like aborted transaction, INSERT IGNORE etc.).
As you change PK values you change the FK relationships they have.
With ID of a type of INT UNSIGNED or BIGINT UNSIGNED you're not going to run out of ID ever.
Related
I'm looking for some help on properly defining an association table with 3 foreign keys in a Sequelize model:
Situation: I'm building an email client, the relative models to this question are:
User Model (user records)
Thread Model (thread records for each new email-thread)
Folder Model (folders for default folders e.g. inbox, sent, etc and custom folders)
ThreadFolder Model (association linking a specific a) User Model, to a specific b) Thread Model, to a specific c) Folder Model)
Problem: My problem is the association model/table (ThreadFolder), I'm not able to create an association for all 3 tables in the ThreadFolder association Model.
First Attempt I'm able to create an association with Sequelize that allows the ThreadFolder model to create foreign keys for 2 of the three models above, but not all 3. Here is the association for that:
Thread.belongsToMany(Folder, { through: ThreadFolder, foreignKey: 'thread_id', otherKey: 'folder_id' })
Folder.belongsToMany(Thread, { through: ThreadFolder, foreignKey: 'folder_id', otherKey: 'thread_id' })
SQL Input Attempts:
user_id: 1 | thread_id: 1 | folder_id: 1 | Successful Insert
user_id: 1 | thread_id: 1 | folder_id: 2 | Successful Insert
user_id: 1 | thread_id: 2 | folder_id: 1 | Failed Insert -- Error below...
user_id: 2 | thread_id: 1 | folder_id: 1 | Successful Insert
user_id: 2 | thread_id: 1 | folder_id: 2 | Successful Insert
First Attempt's Error:
Executing:
INSERT INTO `iwantmail-core`.`thread_folders` (`user_id`, `deleted`, `archived`, `created_at`, `updated_at`, `thread_id`, `folder_id`) VALUES ('1', '0', '0', '2020-03-05 23:34:16', '2020-03-05 23:34:16', '30', '1');
Operation failed: There was an error while applying the SQL script to the database.
ERROR 1062: 1062: Duplicate entry '30-1' for key 'PRIMARY'
SQL Statement:
INSERT INTO `iwantmail-core`.`thread_folders` (`user_id`, `deleted`, `archived`, `created_at`, `updated_at`, `thread_id`, `folder_id`) VALUES ('1', '0', '0', '2020-03-05 23:34:16', '2020-03-05 23:34:16', '30', '1')
Second Attempt I can specify the association as shown below, to allow me to add records with different user_id and folder_id, however, if I use a different thread_id, I get an error shown below.
Folder.hasMany(ThreadFolder, { foreignKey: 'folder_id' })
ThreadFolder.belongsTo(Folder, { foreignKey: 'folder_id' })
Thread.belongsToMany(Folder, { through: ThreadFolder })
Thread.hasMany(ThreadFolder, { foreignKey: 'thread_id' })
ThreadFolder.belongsTo(Thread, { foreignKey: 'thread_id' })
User.hasMany(ThreadFolder, { foreignKey: 'user_id' })
ThreadFolder.belongsTo(User, { foreignKey: 'user_id' })
Folder.belongsToMany(User, { through: ThreadFolder })
SQL Input Attempts:
user_id: 1 | thread_id: 1 | folder_id: 1 | Successful Insert
user_id: 1 | thread_id: 1 | folder_id: 2 | Successful Insert
user_id: 1 | thread_id: 2 | folder_id: 1 | Failed Insert -- Error below...
user_id: 2 | thread_id: 1 | folder_id: 1 | Successful Insert
user_id: 2 | thread_id: 1 | folder_id: 2 | Successful Insert
Second Attempt's Error
Operation failed: There was an error while applying the SQL script to the database.
ERROR 1062: 1062: Duplicate entry '1-1' for key 'PRIMARY'
SQL Statement:
INSERT INTO `mail-core`.`thread_folders` (`user_id`, `thread_id`, `folder_id`) VALUES ('1', '2', '1')
Note that I'm basically trying to indicate that User#1 of Thread#1 are in Folder#1 and as soon as I try to indicate that User#1 of Thread#2 are in Folder#1, the above error occurs.
Help:
Could someone please point me towards the right direction / show how the association should be written to take into account the 3rd association?
Is there a different way to write this association all together so all 3 foreign keys are taken into account in the association table?
Thanks for any help/assistance in advance!
(Relative technologies used: MySQL, MySQL Workbench, Node 12.x, TypeScript, Serverless Framework)
EDIT: Made edits to the post, 2nd attempt was presented as a partial solution, after further testing, both 1st and second attempts fail when a 2nd user is added to the same thread and folder in the association table ThreadFolder.
After looking at your create statements I think you have defined associations thread_folders properly. In my opinion, your second attempt at defining association is correct.
You are getting an error while inserting records because your primary key is the combined key of two attributes namely thread_id and folder_id. Let us say that in your thread_folders table there is already record for thread_id 1 and folder_id 1 then you can not insert another record with thread_id 1 and folder_id 1.
If you remove the combined primary key of thread_id and folder_id then you will be able to insert the records that you want to insert in the thread_folders table.
I hope it helps!
Working solution ended up being a variance of the second attempt:
User.hasMany(ThreadFolder, { foreignKey: 'user_id' })
ThreadFolder.belongsTo(User, { foreignKey: 'user_id' })
Folder.hasMany(ThreadFolder, { foreignKey: 'folder_id' })
ThreadFolder.belongsTo(Folder, { foreignKey: 'folder_id' })
Thread.hasMany(ThreadFolder, { foreignKey: 'thread_id' })
ThreadFolder.belongsTo(Thread, { foreignKey: 'thread_id' })
Most of my model calls (based on how they were written before) will end up changing to start with the association table first e.g.
ThreadFolder.findAll({
where: {
user_id: 1,
folder_id: 1,
},
include: [
{
model: Thread,
include: [
'recipient',
'sender'
]
}
]
})
Hope this helps others that have attempted to do a multi-foreign key association table beyond 2 foreign keys, presumable this approach should work with any amount of foreign keys in the association table.
I got a text column with JSON arrays.
+-------------------------------------------------------------------------+
| code |
+-------------------------------------------------------------------------+
| [] |
| ["5020","6420"] |
| ["4645","4775"] |
| ["6820"] |
| ["2442","2511"] |
| ["4675"] |
| ["1814","6201","6203","6209","6312","6399","7022","7311","7312","7320"] |
| ["6910","6920"] |
| ["4321","4329","4652","7112"] |
| ["4332","7739"] |
+-------------------------------------------------------------------------+
I need to get these codes to another table as single integer values. As soon as there are millions of records I would not like to fetch these records to php/ruby/etc for this task. I'd like to make it inside MariaDB with SQL.
The question is what could be a nice approach for such query?
In addition to the first posted answer about reading table in chunks, some other possible solutions:
1) If it needs to be done once or rarely, I would go with the low-tech approach:
select code into an outfile;
run a simple sed (remove square brackets and replace commas with new lines, thus getting one number per row, quote marks don't matter);
load the file into a table.
2) If you really want to stick with SQL only, there should be a procedure:
use cursor to go through each row;
use substring replacements to convert the array-like string ["1","2"] into the values-like string (1),(2) -- it's simple, although a bit ugly;
append the resulting string to INSERT INTO <table name> VALUES;
run it as a prepared statement;
3) If you want to go fancy and experiment (assuming it's not production), try JSON functions in MariaDB 10.2, also through a procedure:
use cursor to go through each row;
use JSON_LENGTH to get a number of elements in the array;
use a loop (e.g. WHILE) to JSON_EXTRACT each value in turn and either insert it immediately, or again build a prepared statement.
No. The SQL code would be so messy as to be worse overall.
I would read the table in chunks of 100-1000 rows, go through the arrays to get the numbers, de-dup (in php/etc) then do INSERT or INSERT IGNORE into the target table.
Tips on chunking (aimed at DELETE, but adaptable for SELECT): http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks
For PHP. u can use it
$re = '/\d+/m';
$str = '+-------------------------------------------------------------------------+
| code |
+-------------------------------------------------------------------------+
| [] |
| ["5020","6420"] |
| ["4645","4775"] |
| ["6820"] |
| ["2442","2511"] |
| ["4675"] |
| ["1814","6201","6203","6209","6312","6399","7022","7311","7312","7320"] |
| ["6910","6920"] |
| ["4321","4329","4652","7112"] |
| ["4332","7739"] |
+-------------------------------------------------------------------------+';
preg_match_all($re, $str, $matches);
// Print the entire match result
print_r($matches);
Result:
Array
(
[0] => Array
(
[0] => 5020
[1] => 6420
[2] => 4645
[3] => 4775
[4] => 6820
[5] => 2442
[6] => 2511
[7] => 4675
[8] => 1814
[9] => 6201
[10] => 6203
[11] => 6209
[12] => 6312
[13] => 6399
[14] => 7022
[15] => 7311
[16] => 7312
[17] => 7320
[18] => 6910
[19] => 6920
[20] => 4321
[21] => 4329
[22] => 4652
[23] => 7112
[24] => 4332
[25] => 7739
)
)
u should do
$str = Result (MYSQL JSON)
Enjoy.
I am building a popover, in which you can tick checkboxes. The options and choices are stored in a manytomany relationship inside a mysql database.
[ ] option A
[x] option B
[ ] option C
There are 3 tables. sphotos, sphoto_feedback and sphoto_has_feedbacks. sphoto_has_feedbacks stores a sphoto_id, a sphoto_feedback_id and a user_id, to reference the user that has submitted the voting.
sphoto
id | status_id | ...
1 | ...
sphoto_feedback
id | name | ...
11 | Quality |
12 | Creative |
sphoto_has_feedbacks
id | sphoto_id | sphoto_feedback_id | user_id
1 | 1 | 11 | 9999
The Input is user_id => 9999 and sphoto_id => 1. The desired output would be an array, which has all sphoto_feedback entrys, with a boolean variable, like this:
$output = [
"0" => [
"id" => 11,
"name" => "Quality",
"checked" => true
],
"1" => [
"id" => 12,
"name" => "Creative",
"checked" => false
]
]
It would look like this:
[x] Quality <-- stored in sphoto_feedback, also stored in sphoto_has_feedbacks with reference to user
[ ] Creative <-- stored in sphoto_feedback
I want to retrieve all the options from the database and check, if the user has already voted on the options or not.
I know how to do it in PHP with 2 querys, but I'd like to use just one query and would like to know if this is possible.
Use a LEFT JOIN to join the sphoto_feedback and sphoto_has_feedback tables, returning NULL for all the rows in the first table that don't have a match in the second table.
SELECT f.id, f.name, shf.id IS NOT NULL AS checked
FROM sphoto_feedback AS f
LEFT JOIN sphoto_has_feedback AS shf
ON f.id = shf.sphoto_feedback_id
AND shf.sphoto_id = 1 AND shf.user_id = 9999
im making an api in laravel but when i send from a post request it display nothing it work only when i send the values in the url what im i doing wrong here is my code !
$user = new userInscription;
$user->nom = Request::get('name');
$user->pseudo = Request::get('pseudo');
$user->userId = Request::get('userId');
$user->hasFiat = Request::get('hasFiat');
$user->optin = Request::get('optin');
$user->mail = Request::get('mail');
$pseudo = Input::get('pseudo');
$userId = Input::get('userId');
$hasFiat = Input::get('hasFiat');
if($pseudo == '' || $hasFiat == '' )
{
return Response::json( array(
'status' => 'ko',
'message' => 'missing mandatory parameters')
);
}
else if($userId == '')
{
if( $user->save() )
{
$id = DB::table('user')
->where('pseudo','LIKE',$pseudo)
->pluck('userId');
return Response::json(array(
'status' => 'ok',
'message' => 'success',
'userId' => $id
));
}
else
{
return Response::json(array(
'message' => 'error while saving this user !!',
));
}
}
Laravel REST-ful (Resourceful) controlllers has pre-configured routes (can be re-configured):
According to : http://laravel.com/docs/controllers#resource-controllers
+-----------+---------------------------+---------+------------------+
| Verb | Path | Action | Route Name |
+-----------+---------------------------+---------+------------------+
| GET | /resource | index | resource.index |
| GET | /resource/create | create | resource.create |
| POST | /resource | store | resource.store |
| GET | /resource/{resource} | show | resource.show |
| GET | /resource/{resource}/edit | edit | resource.edit |
| PUT/PATCH | /resource/{resource} | update | resource.update |
| DELETE | /resource/{resource} | destroy | resource.destroy |
+-----------+---------------------------+---------+------------------+
Referencing the table each of the Verb must correspond to the action method in the controller.
For example if your Resourceful Route is registered as:
Route::resource('user', 'userInscriptionController');
Then to POST to user resource, you need to have userInscriptionController#store action (i.e. method called store() in your userInscriptionController.
To avoid manually creating each of these actions, you can use Laravel's artisan controller:make
php artisan controller:make userInscriptionController
which will generate all these actions for you, then you just need to fill in your logic to complete the resource.
From your comment, you are using
Route::resource('user', 'userInscriptionController');
which will generate following routes
Verb | Path | Action | Route Name
------------------------------------------------------------------------
GET | /resource | index | resource.index
GET | /resource/create | create | resource.create
POST | /resource | store | resource.store
GET | /resource/{resource} | show | resource.show
GET | /resource/{resource}/edit | edit | resource.edit
PUT/PATCH | /resource/{resource} | update | resource.update
DELETE | /resource/{resource} | destroy | resource.destroy
And as you can see, the only action allowing post is store. So you should use this one or add post route for an other method like this :
Route::post('your_url', array('as' => 'your_route_name', 'uses' => 'YourController#yourMethod'));
I hope it's clear now
if request is GET then:
if (Request::isMethod('get'))
{
$user = new userInscription;
$user->nom = Request::get('name');
$user->pseudo = Request::get('pseudo');
$user->userId = Request::get('userId');
$user->hasFiat = Request::get('hasFiat');
$user->optin = Request::get('optin');
$user->mail = Request::get('mail');
$pseudo = Input::get('pseudo');
$userId = Input::get('userId');
$hasFiat = Input::get('hasFiat');
if($pseudo == '' || $hasFiat == '' )
{
return Response::json( array(
'status' => 'ko',
'message' => 'missing mandatory parameters')
);
}
else if($userId == '')
{
if( $user->save() )
{
$id = DB::table('user')
->where('pseudo','LIKE',$pseudo)
->pluck('userId');
return Response::json(array(
'status' => 'ok',
'message' => 'success',
'userId' => $id
));
}
else
{
return Response::json(array(
'message' => 'error while saving this user !!',
));
}
}
}
===================
if request is POST then:
if (Request::isMethod('post'))
{
$user = new userInscription;
$user->nom = Request::post('name');
$user->pseudo = Request::post('pseudo');
$user->userId = Request::post('userId');
$user->hasFiat = Request::post('hasFiat');
$user->optin = Request::post('optin');
$user->mail = Request::post('mail');
$pseudo = Input::post('pseudo');
$userId = Input::post('userId');
$hasFiat = Input::post('hasFiat');
if($pseudo == '' || $hasFiat == '' )
{
return Response::json( array(
'status' => 'ko',
'message' => 'missing mandatory parameters')
);
}
else if($userId == '')
{
if( $user->save() )
{
$id = DB::table('user')
->where('pseudo','LIKE',$pseudo)
->pluck('userId');
return Response::json(array(
'status' => 'ok',
'message' => 'success',
'userId' => $id
));
}
else
{
return Response::json(array(
'message' => 'error while saving this user !!',
));
}
}
}
I have one games table and two tables to store their scores, game_scores and thirdparty_game_scores with exactly the same structure, something like that:
-------------------------GAMES-------------------------
slug | title | technology | (other non-relevant fields)
-------------------------------------------------------
----------------------GAME SCORES----------------------
id (PK) | game_slug | user | team | score | timestamp
-------------------------------------------------------
----------------THIRDPARTY GAME SCORES-----------------
id (PK) | game_slug | user | team | score | timestamp
-------------------------------------------------------
And their Models like:
class GameScores extends BaseGamesModel {
public function initialize() {
parent::initialize();
$this->belongsTo( 'game_slug', 'Games', 'slug' );
$this->skipAttributes(array('creation_time', 'last_modified'));
}
}
I'm building a weekly ranking with game scores stored only on game_scores:
$ranking = GameScores::sum(
array(
"column" => "score",
"conditions" => $conditions,
"group" => "team",
"order" => "sumatory DESC"
)
);
Is there any way to create a Model that concatenates all data from game_scores and thirdparty_game_scores to create the same ranking without any extra effort?
Thank you so much!
You can set the source table dynamically in your model. See Can I build a Model for two Tables on PhalconPHP?
You should use the setSource() method and put your condition in there, e.g.:
$source = 'default_table';
if (class_name($this) === 'A') {
$source = 'A_table';
}
return $source;