How can I have a table without primary key in Magento? - magento

In Magento, it is necessary that you create a primary key in order your grid and module to work. But, I don't have primary key in my table and don't want to create it. Is it possible to make my module work properly without primary key?
Magento is giving error Column not found: 1054 Unknown column 'main_table.modulename_id' in 'field list' as it doesn't find primary key id in the table while displaying grid.
Without auto-increment it can be done with:
$this->_isPkAutoIncrement = false; in the model. Is there anything like that for primary key as well?
I searched on net without any luck. Any help will be highly appreciated.

If you will not use model/collection for this table, you can do this. If not -- you cann't (without rewrites). See newsletter queue and queue_link tables -- there are no model for queue_link table (it has primary key, but you can use your table without it if you will wok in such way), all things are done in queue resource.

The Magento ORM is setup in a way which will require you specify a primary field. You should always have primary key anyway, I can't imagine a situation where you would want one as it would no longer be suited to a database...
I would imagine you may want a natural/composite key rather than a surrogate key, but I am not sure if that's what you meant?

Related

Foreign key, or no foreign key? Defining Laravel relationships

What is the difference between defining a foreign key VS just creating an integer column named user_id?
// create_posts migrations
$table->integer('user_id')->unsigned();
// vs
$table->foreign('user_id')->references('id')->on('users');
Can they be used interchangeably? What purpose do each one serve? Which is considered a best practice, first or second definition?
Edit
The command $post->user() will work either ways, so what advantages does usage of a foreign key bring?
$table->integer('user_id')->unsigned();
// Above command is creating a column in database and it is required to have the required table structure
$table->foreign('user_id')->references('id')->on('users');
// Above command is creating foreign key index and making reference to id in users table.
As you can see from command explanations they can't be interchangeable, you need first command to have second command without first second command would complain.
Best practise is to use both of them together.
Few of advantages are listed below:
You can implement cascade update/delete.
Database level validation that only valid values of user_id is recorded ( to avoid some one entering 999999 which might be invalid or non existing user_id).
Above two are main advantages and you can express multiple scenarios how above two can be life saviour.
Let's say in post table by human error or bug in script makers user_id = 9999. What you think $post->user() will do?
Unless you can have a post without any reference to user you can see there could be multiple logical issue you may find if foreign keys are not used.
Think of foreign keys as enforcing relations and taking care of post if user is removed / deleted from db.
No, They can't be used interchangeably and each one has its usage. Use index when you want to define index on column, means database index, see here. But when you define a foreign key it set a index to that column (for searching, ...) and also make a relation between user_id and id column in user table, so if there is a user by id 10, then you can use user_id = 10 on another table. Also it has another benefits such as making sure your data are integrated. For example you can't delete user by id 10 if there is article that belongs to this user. For more information see this.
The first line, will only create a user_id column not something special,
while the other line will create a column as a foreign key which will be tightly coupled with id column of users table, this will create some limitations.
read about foreign key reference
For the best practices I always use:
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
Don't mix the definition of index with foreign key, they don't mean the same.

Changing Primary Key in Oracle

I'm updating a table that was originally poorly designed. The table currently has a primary key that is the name of the vendor. This serves as a foreign key to many other tables. This has led to issues with the Vendor name initially being entered incorrectly or with typos that need to be fixed. Since it's the foreign key to relationships, this is more complicated than it's worth.
Current Schema:
Vendor_name(pk) Vendor_contact comments
Desired Schema:
id(pk) Vendor_name Vendor_contact comments
I want to update the primary key to be an auto-generated numeric key. The vendor name field needs to persist but no longer be the key. I'll also need to update the value of the foreign key on other tables and on join tables.
Is the best way to do this to create a new numeric id column on my Vendor table, crosswalk the id to vendor names and add a new foreign key with the new id as the foreign key, drop the foreign key of vendor name on those tables (per this post), and then somehow mark the id as the primary key and unmark the vendor name?
Or is there a more streamlined way of doing this that isn't so broken out?
It's important to note that only 5 users can access this table so I can easily shut them out for a period of time while these updates are made - that's not an issue.
I'm working with SQLDeveloper and Python/Django.
The biggest problem you have is all the application code which references VENDOR_NAME in the dependent tables. Not just using it to join to the parent table, but also relying on it to display the name without joining to VENDOR.
So, although having a natural key as a foreign key is a PITN, changing this situation is likely to generate a whole lot of work, with a marginal overall benefit. Be sure to get buy-in from all the stakeholders before starting out.
The way I would approach it is this:
Do a really thorough impact analysis
Ensure you have complete regression tests for all the functions which rely on the Vendor data
Create VENDOR_ID as a unique key on VENDOR
Add VENDOR_ID to all the dependent tables
Create a second foreign on all the dependent tables referencing VENDOR_ID
Ensure that the VENDOR_ID is populated whenever the VENDOR_NAME is.
That last point can be tackled by either fix the insert and update statements on the dependent tables, or with triggers. Which approach you take will determine on your application design and also the number of tables involved. Obviously you want to avoid the performance hit of all those triggers if you can.
At this point you have an infrastructure which will support the new primary key but which still uses the old one. Why would you want to do this? Because you could go into Production like this without changing the application code. It gives you the option to move the application code to use VENDOR_ID across a broader time frame. Obviously, if developers have been keen on coding SELECT * FROM you will have issues that need addressing immediately.
Once you've fixed all the code you can drop VENDOR_NAME from all the dependent tables, and switch VENDOR_NAME to unique key and VENDOR_ID to primary key on the master table.
If you're on 11g you should check out Edition-Based Redefinition. It's designed to make this sort of exercise an awful lot easier. Find out more.
I would do it this way:
create your new sequence
create table temp as select your_sequence.nextval,vendor_name, vendor_contact, comments from vendor.
rename the original table to something like vendor_old
add the primary key and other constraints to the new table
rename the new table to the old name
Testing is essential and you must ensure no one is working on the database except you when this is done.

How to insert rows in phpMyAdmin

I have a database which I've opened in phpMyAdmin. I clicked the "Insert" button, which has an icon showing one row being inserted between two others.
When I actually try to insert a row, I get the following error:
1062 - Duplicate entry '294' for key 'PRIMARY'
How do I get phpMyAdmin to insert a row (presumably by increasing all the higher-numbered rows by 1) as the icon and the term "Insert" implies? It only seems to want to "Add" a row to the end, not "Insert" it.
As I said, the icon specifically shows one row being inserted between two others, and this is what I want to do. How do I get it to do what it claims it will do?
First, "INSERT" is standard SQL terminology for putting something in the database; it doesn't specifically mean "putting it between two existing values". I see how the icon can be a bit confusing, but when "insertting" data there is no difference between putting something at the end or in the middle of the database. For that matter, there's no real inherent order to data stored in a database; you can select many different ways to sort it when you display the data (and phpMyAdmin generally does a good job of guessing what's reasonable), but data just exists. You can select to sort it by the primary key or alphabetically by user name or any means you wish.
Second, your primary key shouldn't change. It's the key that holds your data together; if you start changing that your references from other tables will be messed up (see below). So don't change that.
Third, if you have your primary key set up with auto_increment (the A_I checkbox in phpMyAdmin), then you shouldn't ever need to set it or worry about it yourself. It's all managed by MySQL. If you aren't happy with the order and want to move 294 to 295 so you can insert something else at 294, then your database design needs tweaking because that's not how auto_incrementing primary keys are designed to work. As a simple solution, you may wish to create another field called "sort_value" or something that you can change.
Which all brings me to the root cause of your trouble: you're trying to create a new row while reusing an existing auto_increment value, and MySQL is smart enough to know this is a bad idea.
So as I said above, changing your primary key (whether or not it's auto generated) is a bad idea, but it may not be obvious why if you only have one table. But relational databases are designed so that you can reference tables from other tables, so for instance a customer database might have a table for "customers", "products", and "purchases" where the purchases table references the primary key ID from both customers and products...imagine the carnage your data would see if you then change the value of those keys in the customer table. You'd show customers associated with some other customer's purchases. So it might not make sense in your database, but overall that's the best way to handle things.
If you really, really don't want to change your database structure, don't reference that key from any other tables, and don't want to listen to my advice, you should be able to simply turn off the auto_increment function on your primary key and reorder them however you wish.

How to use ActiveRecord (without Rails) with database that doesn't have primary keys

I now writing automation program for system based on MSSQL Server, using Ruby 1.9.3 and ActiveRecord 3.1.6 without Rails.
Tables have nonstandard ids (stk_id, urb_id, instead of id), also some tables haven't primary keys.
Before I added column id and set it as primary key my program worked very slowly. I waited nearly 3 minutes while the program makes two operations of selection and some little processing in table with 9000 records. But when I added column id and set it as primary key, these operations were finished in less then 10 secs.
Yet another problem I found in deletion operation: it doesn't work at all without primary key in table. Error when trying to delete without primary key:
undefined method `to_sym' for nil:NilClass
I can't modify the table structure of the production database. Maybe someone knows how to solve this problem without adding id columns and setting primary keys?
Remark: A database without primary keys is BAD !
http://www.helium.com/items/1539899-why-a-relational-database-needs-a-primary-key
Using nonstandard keys is no problem, just use self.primary_key = "stk_id"
You may also use composite_primary_keys:
https://github.com/drnic/composite_primary_keys
Create indexed views on each of the tables with no primary key. A unique clustered index as well as other indexes as needed can be applied. Including a single table in the view should prevent you from violating the many conditions an indexed view requires/prohibits.
I suggest looking into using Sequel instead of ActiveRecord. It is not opinionated about the database schema like ActiveRecord is and may be easier to use with a database schema you can't modify.

ActiveRecord fundamentally incompatible with composite keys?

I have been attempting to use subsonic for a project on which I'm working. All was going quite well until I encountered a link table with a composite primary key. That is a key made up of the primary keys of the two tables it joins. Subsonic failed to recognize both keys which was problematic. I was going to adjust subsonic to support compound keys but I stopped and though "Maybe there is a reason for this". Normally active record relies on a single primary key field for every record, even in link tables. But is this necessary? Should I just give up on active record for this project or continue with my modifications?
Ruby on Rails does not support composite primary keys in model object out of the box. However, there are plugins that accomplish that, for example this.
You can have composite primary key on a join table, but Rails will not create that primary key, you have to create it manually.
See this guide.

Resources