query a table in mysql which does not have primary key - mysql

I am new to database, and run into a time issue when querying a table where no field is indicated as primary key.
for example
+-----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+
| a_id | char(10) | NO | | | |
| media | char(3) | YES | | NULL | |
| label | char(37) | YES | | NULL | |
As you can see, no of the field have any key specification. When I do a query like
"select label from table where a_id=?", the query is extremely slow. Is this caused by the lack of primary key?
thanks,

No, it is caused by lack of indexes. A primary key must contain a unique and non-null value. If you add an index on the column, it may contain duplicates, but your query will still be faster.
If you want the field to be unique, but you don't want it to be a primary key (although you should wonder why), you can even add a unique index. It will force the value to be unique, but it's no primary key.
That can be convenient when you want the table to have an id and a description that should both be unique. Usually you'll make the id the primary key, and the description just unique.

Related

Set a foreign key to nullable in laravel

Assume I have a the tables users and persons. An entry in persons can have a user id or not. So a person can have a user, but this is optional.
This means that the foreign key in persons needs to be nullable.
This is my database migration:
$table->bigInteger('user_id')->nulleable()->unsigned();
$table->foreign('user_id')->nulleable()->references('id')->on('users');
Sadly, when I check the database columns it says, that the field is not nullable
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| user_id | bigint unsigned | NO | MUL | NULL | |
+------------+-----------------+------+-----+---------+----------------+
How can I set the foreign key to nullable? I have tried various combinations I found online, but nothing works.
Thank you very much in advance.
You don't have to repeat nullable (not nulleable) to the second ligne,
try this :
$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users');

MySQL Adding Foreign Key Error 1215

I know such a question is asked before. I made sure that they have the same data type and also checked my syntax, but I am still getting the error:
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(name);
ERROR 1215 (HY000): Cannot add foreign key constraint
mysql> desc `meetings`;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| room | int(6) | NO | | NULL | |
| ownerName | varchar(30) | NO | | NULL | |
| ownerID | varchar(30) | NO | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> desc `employees`;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| username | varchar(30) | NO | PRI | NULL | |
| pswd | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
What am I doing wrong?
name is not primary key in employees table so .. try using username
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(username);
or as suggested by DanielE or you can use the column name but need an UNIQUE index for this column
Change the primary key of 'employees' from user name to name. Then you can use
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(name);
What am I doing wrong? Error 1215 is probably the least of the problems here.
Some of the answers given for this question suggest making username the referenced column in employees rather than name, which is fine as far as it goes, but ignores some really fundamental issues in the schema and quite possibly wasn't the poster's intention for these columns. The rest of this answer is based on my own set of assumptions.
meetings table
Looking at the meetings table, I'm left wondering about the purpose of the ownerID column. Since the intention is to have ownerName as a foreign key to employees, what exactly is ownerID? The name suggests it also somehow references employees, but there is no id or ownerID in employees. Also, if any column starting owner... refers to an employee then why would you need both in the meetings table? One of them is surely redundant. Why is ownerID a VARCHAR(30)? ID columns tend to be INT. Of course, I may be reading to much into this and ownerID may have some other purpose that has nothing to do with an employee, but if that's the case the name is likely going to cause confusion in the future.
The meetings table also has an INT surrogate key in id. There's another INT for room. Since room isn't a foreign key, it suggests that rooms are either consistently identified only by number (which would be strange in my experience) and that there is nothing more to a 'room' that's worth capturing (e.g. location, capacity, equipment etc.) to bother with modelling data about the room in a separate table (again unlikely). Alternatively, room might itself be a foreign key referencing an INT id column in an, as yet undefined, rooms table.
employees table
If we accept ownerID as a more appropriate foreign key to the employee that owns the meeting (it uses less memory to index than either name or username) then consistency would suggest another surrogate key id as the primary key in the employees table. It's not necessary to do this, username would be unique and is fine on it's own, but it's simpler and more efficient. The other suggestion made that name should be the PK in employees is wrong - it presupposes that names are always unique.
A single column to cover an employee name would also be unusual.
The point made about referencing a PK or a unique index is well made (even if it's not strictly necessary in Innodb), I'd just say that ownerName is the wrong foreign key and username and name are the wrong references because there is a better alternative.
And, finally, is a NULL password (pswd) a good idea?

MySQL - Created index isn't showing up as possible key

I have the following table (it has more data columns, removed them because it would be a long post):
CREATE TABLE `members` (
`memberid` int(11) NOT NULL AUTO_INCREMENT,
`firstname` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`lastname` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`memberid`),
KEY `members_lname_ix` (`lastname`)
) ENGINE=InnoDB AUTO_INCREMENT=1019 DEFAULT CHARSET=utf8
COLLATE=utf8_unicode_ci;
By default, a user only ever accesses 10-20 rows from this table at a time and it is usually sorted by the lastname column, it's all paginated server side. so I decided to add an index to lastname to help with sorting, however the index does not seem to be working like I would expect it to. when I run EXPLAIN SELECT * FROM members ORDER BY lastname ASC I get:
id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra
1 | simple | members | ALL | null | null | null | null | 711 | using filesort
I can at least confirm the index exists because if I run SHOW INDEX FROM members I get:
Table | Non_Unique | Key_name | Seq_in_ix | Col_name | Collation | Cardinality | Sub part | Packed | Null | Ix type
members | 0 | PRIMARY | 1 | memberid | A | 711 | null | null | (blank) | BTREE
members | 1 | members_lname_ix | 1 | lastname | A | 711 | null | null | YES | BTREE
if I add USE INDEX (members_lname_ix) both possible_keys and key will remain null. However if I add FORCE INDEX (members_lname_ix) possible_keys remains null and key shows members_lname_ix. This is my first time trying to apply indexing but to me this doesn't seem very intuitive - it feels like mysql should know that I created an index for lastname, no? I can't quite figure out what I'm doing wrong here unless I am misunderstanding something. Is the solution here to just keep using FORCE INDEX?
There are two ways to perform that query:
Plan A (as you were expecting):
Scan through the index sequentially, reading the entire (estimated) 711 rows.
Randomly look up each row in the data BTree. This involves reading the entire dataset.
Deliver the data in order.
Plan B (what it does):
Scan through the data, reading all 711 rows.
Sort the data
Deliver the sorted data.
Plan B does not touch the index at all; this was deemed to be a bigger savings than not having to sort the data.
In a table as tiny as yours, it would be hard to see a difference in speed. (In my test case, it took under 10 milliseconds either way.) In huge tables, the difference could be significant.
For optimal pagination, see http://mysql.rjweb.org/doc.php/pagination

Partitioning with primary key gives Error ERROR 1503 (HY000)

It may sound similar but,I am working on partitioning on some table...the table looks like
mysql> DESC SHOPS;
+-------------------+-------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-------------+------+-----+-------------------+-----------------------------+
| SHOP_ID | int(255) | NO | PRI | NULL | |
| SHOP_NAME | varchar(50) | YES | | NULL | |
| SHOP_CREATED_DATE | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------------------+-------------+------+-----+-------------------+-----------------------------+
3 rows in set (0.00 sec)
so i have search feature where people can search only by shop name so table have around 1 million records so i wanted to RANGE partitioning on shop name alphabetically but i cant do since i have primary key shop_id and shop name can be same...and getting error
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the
table's partitioning function
Solution:
ALTER TABLE SHOPS ADD CONSTRAINT T UNIQUE (SHOP_ID,SHOP_NAME);
And do partitioning ...i cant do this because it does not make sure shop_id is unique(Primary Key)
You can, and you must. Assuming you always let AUTO_INCREMENT do its thing, shop_id will always be unique, and any index starting with shop_id is all you need.
int(255) -- The (255) means nothing. An INT (SIGNED, by default) has a range of -2 billion to +2 billion and occupies 4 bytes, regardless of the (...) after it..
There is probably no performance advantage (or any other advantage) of Partitioning this table. If you think otherwise, please show us a query that you think will benefit.
Please use SHOW CREATE TABLE; it is more descriptive than DESCRIBE.

Get the auto increment-primary key column programatically

witch is the auto increment field in a mysql table?
I have a table structure, for example:
table name is my_table and the fields are my_id, my_name, my_blah.. The one of fields is an auto incremented primary key. Witch is it?
How can I get the name of auto increment field on this table with a php code and/or a mysql query?
You can use the MySQL SHOW COLUMNS query to retrieve information about the columns in a table:
mysql> SHOW COLUMNS FROM `test`;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| col1 | varchar(100) | YES | | NULL | |
| col2 | int(11) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
The extra column will contain auto_increment for the primary key field.
You could try with a
SHOW COLUMNS FROM TableName
See here: http://dev.mysql.com/doc/refman/5.0/en/show-columns.html
Use a MySQL client and issue the query SHOW CREATE TABLE my_table.
It shows you the code one needs to run to create that table. You can see the column names, types (and lengths), other attributes each column may have (they depend on the type). AUTO_INCREMENT is such an attribute.
It also shows you the PK and the indexes of the table.