adding unique to existing foreign key - mysql

i have this table
CREATE TABLE IF NOT EXISTS `transaction` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`amount` bigint(20) NOT NULL,
`req_id` int(11) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `transactions_873a2484` (`req_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=914 ;
i want to change this forign key transactions_873a2484 to a unque forign key
basically i want to change it to
UNIQUE KEY `transactions_req_id_de2b5683_uniq` (`req_id`),
i already have lots of data in my table otherwise i would have just remake this table .... is there anyway to do this withouth harming the data ?

I will improve this as I go. MySQL will honor your wishes, even allow you to shoot yourself in the foot as you go:
create table t9
(
id int auto_increment primary key,
thing varchar(20) not null,
key(thing),
unique key (thing),
unique key `yet_another` (thing)
);
-- warning 1831 dupe index
show create table t9;
CREATE TABLE `t9` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`thing` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `thing_2` (`thing`),
UNIQUE KEY `yet_another` (`thing`),
KEY `thing` (`thing`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
So look at all the baggage it you have to carry around with your upserts (read: slow extra unnecessary indexes).
So if you want it as lean as possible, as I mentioned in comments, unwind things first by dropping the FK's in the child tables, the referencing first. See This Answer.
Then drop the current non-unique parent key:
DROP INDEX index_name ON tbl_name;
Then add the unique key in the parent. This is the new referenced:
CREATE UNIQUE INDEX idxName ON tbl_name (colName);
Then add the FK's in the children (the referencing)
CREATE INDEX idxName ON child_tbl_name (colName);
You can get the key names by show create table theTableName or by SHOW INDEX. Use fresh names for the new ones, it doesn't matter.
Such as:
mysql> show index from t9;
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t9 | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 0 | thing_2 | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 0 | yet_another | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
| t9 | 1 | thing | 1 | thing | A | 0 | NULL | NULL | | BTREE | | |
+-------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

ALTER TABLE `transaction`
DROP INDEX `transactions_873a2484`,
ADD UNIQUE(req_id);
You cannot turn a non-unique into UNIQUE, but the above should do the equivalent. The data will be unharmed.

Related

MySQL report query optimization and timezone issues

I'm faced with a MySQL database which contains an events table with ~70 million rows which has foreign keys to other tables and is used to generate reports. Constructing a performant query to select (while counting/summing values) and grouping data per day from this table is proving challenging.
The database structure is as follows:
CREATE TABLE `client` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_client_id_name` (`id`,`name`)
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb3
CREATE TABLE `class` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`client_id` int DEFAULT NULL,
`duration` int DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_client_id_idx` (`client_id`),
CONSTRAINT `fk_client_id` FOREIGN KEY (`client_id`) REFERENCES `client` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2606 DEFAULT CHARSET=utf8mb3
CREATE TABLE `event` (
`id` int NOT NULL AUTO_INCREMENT,
`start_time` datetime DEFAULT NULL,
`class_id` int DEFAULT NULL,
`venue_id` int DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_class_id_idx` (`class_id`),
KEY `fk_venue_id_idx` (`venue_id`),
KEY `idx_1` (`venue_id`,`class_id`,`start_time`),
CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `fk_venue_id` FOREIGN KEY (`venue_id`) REFERENCES `venue` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=64093231 DEFAULT CHARSET=utf8mb3
CREATE TABLE `venue` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_venue_id_name` (`id`,`name`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb3
The query which is fine on an events table with a few thousand rows to demonstrate the desired outcome is as follows:
SELECT
CAST(event.start_time as date) as day,
class.name,
client.name,
venue.name,
COUNT(class.name) AS occurrences,
SUM(class.duration) AS duration
FROM
class,
client,
event,
venue
WHERE
event.venue_id = venue.id
AND event.class_id = class.id
AND class.client_id = client.id
GROUP BY day, class.name, client.name, venue.name
The database isn't indexed and although I've tried indexing with things like alter table events add index idx_test (venue_id, class_id, start_time); to improve performance it's still incredibly slow (I tend to abort them when they're past the 10 minute mark so don't know for sure how long they'd take to complete).
I figured this was a good use case for a summary table (as suggested by Rick James' guide) so that I could hold a separate set of summarized data broken down into day with occurrences and total duration calculated/incremented with each addition to the table (IODKU). However I'm then also up against creating rows per day in a summary table based on what is considered a day in the database (UTC) which may not match with the application's "day" due to timezone offset.
Short of converting the start_time column to a timestamp type (which is then inconsistent with all other date types in the database) is there any way round this or is there any other optimization I could be making to the original events table resulting in a more responsive query? TIA
Update 23/05
Here's the buffer pool size:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
I've also made a bit of progress with indexing, modifying the query and creating a summary table.
I tried various ordering of columns to test indexes and found idx_event_venueid_classid_starttime (below), to be the most efficient for the event table:
SHOW INDEXES FROM EVENT;
+-------+------------+-------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+-------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| event | 0 | PRIMARY | 1 | id | A | 62142912 | NULL | NULL | | BTREE | | | YES | NULL |
| event | 1 | fk_class_id_idx | 1 | class_id | A | 51286 | NULL | NULL | YES | BTREE | | | YES | NULL |
| event | 1 | fk_venue_id_idx | 1 | venue_id | A | 16275 | NULL | NULL | YES | BTREE | | | YES | NULL |
| event | 1 | idx_event_venueid_classid_starttime | 1 | venue_id | A | 13378 | NULL | NULL | YES | BTREE | | | YES | NULL |
| event | 1 | idx_event_venueid_classid_starttime | 2 | class_id | A | 81331 | NULL | NULL | YES | BTREE | | | YES | NULL |
| event | 1 | idx_event_venueid_classid_starttime | 3 | start_time | A | 63909472 | NULL | NULL | YES | BTREE | | | YES | NULL |
+-------+------------+-------------------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
Here's my modified version of the query, using JOIN syntax and now uses CONVERT_TZ to convert from UTC to the timezone required for reporting and then group that by the date (discarding the time portion):
SELECT
DATE(CONVERT_TZ(event.start_time,
'UTC',
'Europe/London')) AS tz_date,
class.name,
client.name,
venue.name,
COUNT(class.id) AS occurrences,
SUM(class.duration) AS duration
FROM
event
JOIN
class ON class.id = event.class_id
JOIN
venue ON venue.id = event.venue_id
JOIN
client ON client.id = class.client_id
GROUP BY tz_date, class.name, client.name, venue.name;
And here's the output of explain for that query:
+----+-------------+--------+------------+--------+---------------------------------------------------------------------+-------------------------------------+---------+-------------------------+------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+--------+---------------------------------------------------------------------+-------------------------------------+---------+-------------------------+------+----------+------------------------------+
| 1 | SIMPLE | venue | NULL | index | PRIMARY,idx_venue_id_name | idx_venue_id_name | 772 | NULL | 28 | 100.00 | Using index; Using temporary |
| 1 | SIMPLE | event | NULL | ref | fk_class_id_idx,fk_venue_id_idx,idx_event_venueid_classid_starttime | idx_event_venueid_classid_starttime | 5 | example.venue.id | 4777 | 100.00 | Using where; Using index |
| 1 | SIMPLE | class | NULL | eq_ref | PRIMARY,fk_client_id_idx | PRIMARY | 4 | example.event.class_id | 1 | 100.00 | Using where |
| 1 | SIMPLE | client | NULL | eq_ref | PRIMARY,idx_client_id_name | PRIMARY | 4 | example.class.client_id | 1 | 100.00 | NULL |
+----+-------------+--------+------------+--------+---------------------------------------------------------------------+-------------------------------------+---------+-------------------------+------+----------+------------------------------+
The query takes ~1m 20s to run now so I figured I could prepend that with an insert into to populate a summary table with the dates being timezone specific and run that on a nightly basis. Summary table structure:
CREATE TABLE `summary` (
`tz_date` date NOT NULL,
`class` varchar(255) NOT NULL,
`client` varchar(255) NOT NULL,
`venue` varchar(255) NOT NULL,
`occurrences` int NOT NULL,
`duration` int NOT NULL,
PRIMARY KEY (`tz_date`,`class`,`client`,`venue`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
From the original ~60m+ rows in the event table, the aggregated summary table is populated with ~66k rows.
To then generate the reports from the summary table it takes a fraction of a second (shown below with data snipped):
SELECT * FROM SUMMARY;
66989 rows in set (0.03 sec)
I haven't looked into the impact of inserting into event while the query to populate the summary table is running - is using InnoDB likely to slow that down?
No further indexes are likely to help. It need to scan all the events table, reaching into the other tables to get the names.
Some things for us to look at:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
EXPLAIN SELECT ...
How much RAM do you have?
Do the aggregates (COUNT and SUM) look correct? In some situations involving JOIN, they can be over-inflated.
Please use the newer JOIN ... ON syntax. (Won't change performance.)
As you observed, a Summary Table may help -- but only of the older data is not being modified. Please provide the SHOW CREATE TABLE and query for it.
Yes, timezone vs "definition of day" is a thorny issue. Notice how StackOverflow defines day based on UTC.
How many new rows are there per day? Are they spread out somewhat evenly throughout the day? If the average number of rows per hour is at least 20, then the Summary Table could be based on half-hour intervals. (I picked that because of India time vs most of the rest of the world.) The 20 comes from a Rule of Thumb that says that a summary table should have one-tenth as many rows as the Fact table.
Yes, TIMESTAMP instead of DATETIME may be a workaround.
Since you are talking about moderately large tables, consider whether to change INT NULL to SMALLINT UNSIGNED NOT NULL or some other sized integer.
(As for the cliff in 2038, ask yourself how many databases have been active on the same hardware and software since 2006. That may give some perspective on whether your design must survive 16 years.)

How to drop unique constraint from mysql table on a foreign key column

I want to drop just the UNIQUE Constraint from my MySQL table column and keep the Foreign Key Constraint on the column as-is. work_id is the foreign key. Initially, the column was supposed to be unique (one-to-one relationship) which is now not needed.
I'm using MySQL Ver 15.1 Distrib 5.5.64-MariaDB.
DESCRIBE requests;
+---------------------+---------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------------------------------------+------+-----+---------+-------+
| request_id | char(32) | NO | PRI | NULL | |
| owner | varchar(100) | NO | | NULL | |
| status | enum('PENDING','ACCEPTED','REJECTED') | YES | | NULL | |
| work_id | char(32) | NO | UNI | NULL | |
| response_message | varchar(3000) | YES | | NULL | |
| created_date | datetime | NO | | NULL | |
| last_modified_date | datetime | NO | | NULL | |
+---------------------+---------------------------------------+------+-----+---------+-------+
CREATE TABLE `requests` (
`request_id` char(32) NOT NULL,
`owner` varchar(100) NOT NULL,
`status` enum('PENDING','ACCEPTED','REJECTED') DEFAULT NULL,
`work_id` char(32) NOT NULL,
`response_message` varchar(3000) DEFAULT NULL,
`created_date` datetime NOT NULL,
`last_modified_date` datetime NOT NULL,
PRIMARY KEY (`request_id`),
UNIQUE KEY `work_id` (`work_id`),
CONSTRAINT `requests_ibfk_1` FOREIGN KEY (`work_id`) REFERENCES `work` (`work_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
I want to remove UNIQUE Constraint from the work_id. I did some search and executed the following commands.
SHOW INDEX FROM requests;
+-----------------+------------+----------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+----------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| requests | 0 | PRIMARY | 1 | request_id | A | 16 | NULL | NULL | | BTREE | | |
| requests | 0 | work_id | 1 | work_id | A | 16 | NULL | NULL | | BTREE | | |
+-----------------+------------+----------------+--------------+-------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
And then executed
ALTER TABLE requests DROP INDEX work_id;
I get an error
ERROR 1553 (HY000): Cannot drop index 'work_id': needed in a
foreign key constraint
So, your problem is you are trying to drop a index which is used in Foreign Key Constraint. So you can not do it directly. Follow below steps:
Drop the constraint requests_ibfk_1 which is your foreign key.
alter table requests drop foreign key requests_ibfk_1
Then Drop the UNIQUE KEY on column work_id.
alter table requests drop index work_id
Again Add Foreign Key on Column work_id.
alter table requests add CONSTRAINT `requests_ibfk_1` FOREIGN KEY (`work_id`) REFERENCES `work` (`work_id`)
DEMO
The problem is that the definition of the unique constraint drops the index which is normally created for the foreign key. But there is another way, without recreating the foreign key constraint or (temporarily) disabling the checks (which can lead to consistency errors).
First, add another index for the same column (for logical reasons, I would name it exactly as the foreign key):
CREATE INDEX requests_ibfk_1 ON requests(work_id);
Now you can safely drop the unique constraint/index (since there is still an index available for the foreign key constraint):
DROP INDEX work_id ON requests;
I hope this solves the problem.
As described in #Rick James's comment , the alternative is to temporarily disable key constraints of a table, immediately drop the unique index, and then enable the keys of the table afterwards. Here is an example for mysql / mariadb :
ALTER TABLE `<YOUR_TABLE_NAME>` DISABLE KEYS;
ALTER TABLE `<YOUR_TABLE_NAME>` DROP INDEX `<YOUR_UNIQUE_INDEX_NAME>`;
ALTER TABLE `<YOUR_TABLE_NAME>` ENABLE KEYS;

Trying to remove a primary key from MySQL table

Edit: Not sure why this is marked as a duplicate. The error I am getting is different
I am trying to remove a primary key definition but am receiving an error for some reason.
mysql> ALTER TABLE `aux_sponsors` DROP PRIMARY KEY;
ERROR 1091 (42000): Can't DROP 'PRIMARY'; check that column/key exists
mysql> desc aux_sponsors;
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| unit | varchar(8) | NO | | MF | |
| code | varchar(32) | NO | PRI | NULL | |
| userid | varchar(32) | NO | | | |
| fullName | varchar(64) | NO | | | |
| department | varchar(255) | NO | | | |
| description | varchar(255) | NO | | NULL | |
+-------------+--------------+------+-----+---------+-------+
6 rows in set (0.01 sec)
Am I doing something wrong here? I simply want no more primary key in this table.
mysql> SHOW CREATE TABLE aux_sponsors;
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| aux_sponsors | CREATE TABLE `aux_sponsors` (
`unit` varchar(8) NOT NULL DEFAULT 'MF',
`code` varchar(32) NOT NULL,
`userid` varchar(32) NOT NULL DEFAULT '',
`fullName` varchar(64) NOT NULL DEFAULT '',
`department` varchar(255) NOT NULL DEFAULT '',
`description` varchar(255) NOT NULL,
UNIQUE KEY `code` (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
You don't have a PRIMARY KEY; you have a UNIQUE key. So, you can't do this:
ALTER TABLE `aux_sponsors` DROP PRIMARY KEY
Instead, just do
ALTER TABLE `aux_sponsors` DROP KEY `code`
DESC (a/k/a DESCRIBE) is not a true MySQL feature; according to the docs, "The DESCRIBE statement is provided for compatibility with Oracle."
More from the documentation:
A UNIQUE index may be displayed as PRI if it cannot contain NULL values and there is no PRIMARY KEY in the table. A UNIQUE index may display as MUL if several columns form a composite UNIQUE index; although the combination of the columns is unique, each column can still hold multiple occurrences of a given value.
In your case, the column code is NOT NULL and is the only column in a UNIQUE key, so DESC is showing it as PRI. Because of this type of problem, it's better to use SHOW INDEX to find out the types of keys on a table.

Horrible MySQL index behavior with a simplest IN statement

I have found that MySQL (Win 7 64, 5.6.14) does not use index properly if I specify table output for IN statement. USER table contains 900k records.
If I use IN (_SOME_TABLE_OUTPUT_) syntax - I get fullscan for all 900k users. Query runs forever.
If I use IN ('CONCRETE','VALUES') syntax - I get a correct index usage.
How can I make MySQL finally USE the index?
1st case:
explain SELECT gu.id FROM USER gu WHERE gu.uuid in
(select '11b6a540-0dc5-44e0-877d-b3b83f331231' union
select '11b6a540-0dc5-44e0-877d-b3b83f331232');
+----+--------------------+------------+-------+---------------+------+---------+------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+-------+---------------+------+---------+------+--------+--------------------------+
| 1 | PRIMARY | gu | index | NULL | uuid | 257 | NULL | 829930 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 3 | DEPENDENT UNION | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------------+------------+-------+---------------+------+---------+------+--------+--------------------------+
2nd case:
explain SELECT gu.id FROM USER gu WHERE gu.uuid in
('11b6a540-0dc5-44e0-877d-b3b83f331231');
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
| 1 | SIMPLE | gu | ref | uuid | uuid | 257 | const | 1 | Using where; Using index |
+----+-------------+-------+------+---------------+------+---------+-------+------+--------------------------+
Table structure:
CREATE TABLE `USER` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`email` varchar(255) DEFAULT NULL,
`uuid` varchar(255) NOT NULL,
`partner_id` bigint(20) NOT NULL,
`password` varchar(255) DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique-email` (`partner_id`,`email`),
KEY `uuid` (`uuid`),
CONSTRAINT `fk_USER_partner` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`) ON DELETE CASCADE,
CONSTRAINT `FKB2D9FEBE725C505E` FOREIGN KEY (`partner_id`) REFERENCES `partner` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3315452 DEFAULT CHARSET=latin1
FORCE INDEX and USE INDEX statements don't change anything.
Demonstration SQLfiddle: http://sqlfiddle.com/#!2/c607e1/2
In fact I faced such problem before and it happened that I had one table that had a single column set as UTF-8 and the other tables where latin1. It did not matter what I did, MySQL insisted on using no indexes. The problem is quite well described on this blog post Slow queries in MySQL due to collation problems. Once you manage to fix the character set, I believe any of the queries will work.
An inner join on your virtual table might give you better performance. Try something along these lines.
SELECT gu.id
FROM USER gu
INNER JOIN (
select '11b6a540-0dc5-44e0-877d-b3b83f331231' uuid
union all
select '11b6a540-0dc5-44e0-877d-b3b83f331232') ids
on gu.uuid = ids.uuid;

Query to determine whether a certain compound primary key has been used?

I have a mysql table with a compound primary key. The table definition looks like(some column omitted):
CREATE TABLE `wasteitem` (
`categoryid` char(4) NOT NULL,
`classid` char(4) NOT NULL,
`LIflag` int(11) NOT NULL,
PRIMARY KEY (`categoryid`,`classid`)
);
And I want to determine if any of known keys have been used.
If the table have only a simple primary key I can use query like this:
select categoryid from wasteitem where categoryid in ('key1','key2','key3','key4')
Things to be concerned:
The primary key is a compound key.
The known keys in the list might be very long.
This table is very big(26GB)
You could put the keys you're interested in in another (temporary) table, and join.
use it, to look for keys
DESCRIBE wasteitem
that would be something similar:
mysql> describe wasteitem;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| categoryid | char(4) | NO | PRI | NULL | |
| classid | char(4) | NO | PRI | NULL | |
| LIflag | int(11) | NO | | NULL | |
+------------+---------+------+-----+---------+-------+
3 rows in set (0.00 sec)