I am having trouble inserting data into a MySQL table using CakePHP. I am making a table that once a row is inserted, it should not be able to be overwritten. With the save method of CakePHP, if I try to enter something with the same primary key but different information, it will just update that entry instead of returning an error. I tried to unset the id for the model and also tried to do Model->create() before the call, but it still just overwrites the data.
Additionally, I have been trying to use the Model->query() method instead, but I cannot get it to properly check for errors. I want it to insert, but return an error message if the ID is already taken, so I tried this.
$insertQuery = ("INSERT INTO `students` VALUES ('{$id}', '{$lastname}', '{$firstname}', '')");
$this->Student->query($insertQuery) or die("error" .mysql_error());
However, the query command returns an array and not a truth value, so this will call die every time. I would appreciate any advice someone can give.
Your table should have only the Id as the primary key and it should be IDENTITY.
In CakePHP if you dont specify the Id in the form you create to submit your data it will create another record, even with the same values.
But you should revise your model to be sure that the id is not required or something like that.
Related
I have a Model with an auto-incrementing primary key. I want to be able to create an object from that model without an id, throw it away, and not have that Column's id auto-increment. Is that possible?
Assigning MyModel(id=None) does not do that.
Assigning MyModel(id=0) does not work either. It results in a Key (id)=(0) already exists. response.
To clarify: I want to keep the Column as auto-incrementing, but disable that behavior in specific circumstances.
The goal is to have a MyModel instance not saved in the database which I can pass to the template and can treat just like any other. For example, I want to print myModel.attribute in a template, but without saving myModel or incrememting the Column's id counter.
This is Postgres/Python/Flask/SQLAlchemy.
The problem is the instance is being auto-flushed. Not including session.add(myModel) does not fix it, but here are three solutions.
session.autoflush=False
this isn't great because it applies to everything after that line
session.expunge(myModel)
this might throw an exception and needs to be wrapped in a try/except
from sqlalchemy.orm import make_transient and make_transient(myModel)
this is what I went with
Currently, I am trying to move from an Access backend to a SQL backend for my database while still keeping the Access form as the frontend. This is done via linked tables with ODBC connections to my backend. The form is designed to add new records to the table. The problem is with AutoNumber. The ID was set as an AutoNumber and the form would simply display (New) while waiting for the user to add the remaining columns. I have set up my SQL data with the IDENTITY property, so it will increment once a new record is created. However, I cannot get the form to behave the same way as it did because, even though the backend will automatically add the next sequential ID, I cannot automatically fill that data into the form prior to a user actually saving the form data. Is there a way maintain the form functionality that AutoNumber provides?
TL;DR: Form is not working correctly after AutoNumber is changed to Number.
Well, there are "rare" cases in which you actually need the autonumberr before you save the record. For example, if you have a sub-form, then Access ALWAYS does a automatic save of the main record, and thus the autonumber is and will have been created .So a main form, and sub form (child table) will work fine, and do so without code.
Now, there are some cases in which you need the autonumber. Say you have some "code" that needs to run and spit out some child records.
The general approach is to simply execute a record save at that point in time.
So, say there is a button, or some code you need to run in the form, and you NEED the PK autonumber?
You can use this code:
If isnull(me!ID) = true then
me.dirty = false ' force record save - autonumber now created
end if
the record for above to work will have to be "dirty", but in near all cases, this tends to be the case. The "rare" exceptions would suggest that you could check me.IsNewRecord, but in most cases the above bit of code will suffice.
I can't really imagine that the "display" of some autonumber is oh so important WHEN the user is starting to enter data.
However, if you want the autonumber to appear after ANY keypress (data entry on the form)?
Simply put this line of code in the after insert event:
me.dirty = false
So, now when looking at a form, the FIRST key press by the user in any text box will force the autonumber to be generated and appear. However, it is a VERY bad practice to assign any meaning of the autonumber ID to the end users. In fact that ID should in most cases be hidden.
the only issue or downside of above is of course that if you have any required columns, then the above may error out or case an issue.
Solution
For this problem, I needed to set my identity_insert to ON in the SQL backend. Here is the code to do so:
SET IDENTITY_INSERT tableName ON;
Also, if you get the error: Table <Table Name> does not have the identity property. recreate the table with the autoincrementing column having an identity.
Example:
CREATE TABLE new_employees (id_num int IDENTITY(1,1), fname varchar (20), minit char(1), lname varchar(30));
More on IDENTITY in Microsoft offical documentation: here
I know getting the id of a record from a db table in CakePHP is easy. I want to get the "future" id of a "future" record of a table, that is, I'll insert a record, but before inserting, I want to get its id, which will be generated by db after insertion is completed(the id is int, Auto Increment). Thanks.
Even the database itself doesn't know what ID it's going to use until the very moment after the record is saved.
You can't (in a multi-user system) ask in advance what the ID is going to be because 20 other records may have been inserted between the time you ask what the ID is going to be, and when you insert your record (with an ID that was used 20 records ago.) This is called a 'Race Condition'.
Here's what will happen:
You: DB - what's the next ID please?
DB: (Does a max() on the column) 21!
You: Great! I'll use that!
(meanwhile 20 other records get inserted by other users)
You: Hi DB, I'd like to insert this record using ID 21 like you told me!
DB: Oops - sorry - that ID has already been used :'-(
You don't NEED to know the record in advance. If you structure your save data correctly, and use CakePHP's saveAccociated() method, CakePHP will insert the correct ID as the foreign key value for all your related data.
The only way to have a predictable ID is to create it yourself. Remember - it MUST be non-null and unique (the definition of a primary key).
Save yourself many, many future primary key clashes and stick to the cake method :-)
One option is you can get the current max id from mysql and then just increment the value. If you have alot of operations going on this might cause some trouble with your site. But you could use:
$this->Model->query("SELECT MAX(id) as max FROM `your_table_name`");
This would get you the max id of that table currently then you can do a +1
Another option would be to get the ID after you save, then update your record with that ID. For example cakephp has a method for this.
$this->Model->getLastInsertID();
$this->Model->updateAll($fields, $conditions)
Reference updateAll: http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-updateall-array-fields-array-conditions
I have a Users and a Reports table, connected with HABTM relationship.
I can save a report that creates a correct record in reports_users table, I can view the relationship table by using $this->User->ReportsUser->.., and so on.
Now I want to delete a specific row in reports_users table, but I can't seem to do it.
I have tried the following:
$this->User->ReportsUser->deleteAll(array(
'ReportsUser.report_id' => $this->data['Report']['report_id'],
'ReportsUser.user_id' => $this->data['Report']['user_id']
));
..but it deletes all the rows with the given user_id, with this query:
What am I doing wrong here. Is it a bad data in the deleteAll call?
I don't want to delete any users or reports, only the relationship between them.
I can confirm that the table names are correct, and that the variables exist and are set.
It seems no error with your code. Either your $this->data['ReportUser']['report_id'] is having some problem. The best way is to first try to print your $this->data. And check whether it exists?
For the safety reasons, use the second argument $cascade = false and also unbind all the ReportUser model Associationship using $this->ReportUser->unbindModel() method.
The other reason seems to be deleting data through
$this->User->ReportUser. Try to use $this->ReportUser->deleteAll('your conditions', false); directly.
Please ask if it not worked for you.
I've added two new fields to my subscription database table namely first_name and last_name to table subscriptions
But whenever I get my values returned from the form and I try to save them then it's not saving to the database?
My code is as follows
$this->data['Subscription']['id'] = $subscription['Subscription']['id']; //To get the primary key
$this->data['Subscription']['first_name']; //Echoes out the name I entered
$this->data['Subscription']['last_name']; //Echoes out the surname I entered
Then I call $this->Subscription->save(); WHICH SAVES ALL OTHER FIELDS except the fields I've newly added to the table, I tried $this->Subscription->set($this->data['Subscription']); and also nothing wants to save?
I'm not sure what I'm doing wrong here? Any help will be higly appreciated!!!!
Assuming that you run the app with debug 0 you need to delete the cache in /tmp because the database schema is cached by CakePHP.
According to your description, you forgot to add $this->data to save, you must save your data like so:
$this->Subscription->save( $this->data );