mysql - check before creating - mysql

I am creating tables in mysql 5.7 version, such as but would like to check if table exists before creating. or another scenario have some try catch block , where if table exits and i execute create again, it throws an error . i can catch that and log it.
CREATE TABLE `address` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`CreateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`UpdateTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`UserId` int(11) DEFAULT NULL,
`Address1` varchar(100) CHARACTER SET utf8 NOT NULL,
`Address2` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
`City` varchar(50) CHARACTER SET utf8 NOT NULL,
`State` int(11) NOT NULL,
`Zip` varchar(9) NOT NULL,
PRIMARY KEY (`Id`),
KEY `fk_address_user_UserId_idx` (`UserId`),
CONSTRAINT `fk_address_user_UserId` FOREIGN KEY (`UserId`) REFERENCES `user` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

If you can dynamize schema and table names I've written a udf once to be used in a stored procedure like:
IF fn_table_exists('my_schema', 'table_to_be_created') THEN
SELECT 'Table Already exists!';
END IF;
Implementation:
DELIMITER $$
CREATE FUNCTION fn_table_exists(dbName VARCHAR(255), tableName VARCHAR(255)) RETURNS TINYINT(1)
BEGIN
DECLARE totalTablesCount INT DEFAULT (
SELECT COUNT(*)
FROM information_schema.TABLES
WHERE (TABLE_SCHEMA COLLATE utf8_general_ci = dbName COLLATE utf8_general_ci)
AND (TABLE_NAME COLLATE utf8_general_ci = tableName COLLATE utf8_general_ci)
);
RETURN IF(
totalTablesCount > 0,
TRUE,
FALSE
);
END$$
DELIMITER ;

Related

MySQL - Copy row to another table with foreign key

i want to copy 1 row from this table:
tableold
-----------
oid (primary key, auto_incremment)
name
age
detail
to this table:
tablenew
------------
nid (primary key, auto_incremment)
fid (foreign key to another table)
name
age
detail
With this SQL-Command:
INSERT INTO tablenew (tablenew.name, tablenew.age, tablenew.detail)
SELECT tableold.name, tableold.age, tableold.detail
FROM tableold
WHERE tableold.oid = 123;
But i get the error:
ERROR 1364 (HY000): Field 'fid' doesn't have a default value
Is there any possibility to manually add the foreign key 'fid' to the SQL-Command?
*Edit, i have added the CREATE table statements:
CREATE TABLE `othertable` (
`fid` int NOT NULL AUTO_INCREMENT,
`value1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`value2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`value3` longtext CHARACTER SET utf8 COLLATE utf8_general_ci,
`value4` longtext CHARACTER SET utf8 COLLATE utf8_general_ci,
PRIMARY KEY (`fid`),
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8;
CREATE TABLE `tablenew` (
`nid` int NOT NULL AUTO_INCREMENT,
`fid` int NOT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`age` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`detail` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`sid`),
KEY `fid_fkey` (`fid`),
CONSTRAINT `fid_fkey` FOREIGN KEY (`fid`) REFERENCES `othertable` (`fid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
CREATE TABLE `tableold` (
`oid` int NOT NULL AUTO_INCREMENT,
`name` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`age` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`detail` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`oid`)
) ENGINE=InnoDB AUTO_INCREMENT=157 DEFAULT CHARSET=utf8;
I have solved it:
INSERT INTO tablenew (tablenew.fid, tablenew.name, tablenew.age, tablenew.detail)
SELECT 'value', tableold.name, tableold.age, tableold.detail
FROM tableold
WHERE tableold.oid = value;

Mysql Truncated incorrect DOUBLE value error for string checking

I have a stored procedure
CREATE PROCEDURE `DeleteAttachmentsByIDs`(IN p_ids nvarchar(1024), IN p_modifiedBy varchar(100), IN p_modifiedDate datetime)
BEGIN
update attachments set
`IsDeleted` = 1
, `ModifiedBy` = p_modifiedBy
, `ModifiedDate` = p_modifiedDate
where
id IN (p_ids);
END
Now I called with
CALL `DeleteAttachmentsByIDs`('12479,12480,12481', 'admin', '2019-04-02 15:32:30.558178')
And it comes the error
Error Code: 1292. Truncated incorrect DOUBLE value: '12479,12480,12481'
The create table command for attachments table is
CREATE TABLE `attachments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ObjectID` int(11) DEFAULT NULL,
`ObjectName` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`Category` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
`ContentType` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`ContentLength` bigint(20) DEFAULT NULL,
`FileName` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`Data` longblob,
`Description` varchar(500) CHARACTER SET utf8 DEFAULT NULL,
`CreatedBy` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
`CreatedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ModifiedBy` varchar(100) CHARACTER SET utf8 DEFAULT NULL,
`ModifiedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`IsDeleted` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `Index1` (`id`,`ObjectID`,`ObjectName`,`IsDeleted`)
) ENGINE=InnoDB AUTO_INCREMENT=12482 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
I think this may be caused by the 'in' condition which need array, however string is passed in. I think I need to split the string into array to make the 'in' works. Is that correct and how I can do it?
You can use FIND_IN_SET in this case:
CREATE PROCEDURE `DeleteAttachmentsByIDs` (IN p_ids NVARCHAR(1024), IN p_modifiedBy VARCHAR(100), IN p_modifiedDate DATETIME)
BEGIN
UPDATE attachments SET
`IsDeleted` = 1,
`ModifiedBy` = p_modifiedBy,
`ModifiedDate` = p_modifiedDate
WHERE FIND_IN_SET(id, p_ids) > 0 AND id <> 0; -- AND id <> 0 to support safe-mode.
END
Another solution can be the following, using a string comparison with LIKE:
CREATE PROCEDURE `DeleteAttachmentsByIDs` (IN p_ids NVARCHAR(1024), IN p_modifiedBy VARCHAR(100), IN p_modifiedDate DATETIME)
BEGIN
UPDATE attachments SET
`IsDeleted` = 1,
`ModifiedBy` = p_modifiedBy,
`ModifiedDate` = p_modifiedDate
WHERE CONCAT(',', p_ids, ',') LIKE CONCAT('%,', id, ',%') AND id <> 0; -- AND id <> 0 to support safe-mode.
END
The MySQL Workbench is using safe-mode by default. So you can add AND id <> 0 to suppress the error thrown by MySQL Workbench. Read more about the safe-mode here: MySQL error code: 1175 during UPDATE in MySQL Workbench

Optimize MySQL trigger performance

I have following table structure. Added two triggers, but as the triggers work with string values and they search for string the database performance might degrade in future when every table will get huge. I have no strong experience with indexes, and don't know which fields to index to make trigger's search operation fast even with millions of rows.
What do you suggest?
CREATE TABLE `ofRoster` (
`rosterID` bigint(20) NOT NULL,
`username` varchar(64) NOT NULL,
`jid` varchar(1024) NOT NULL,
`sub` tinyint(4) NOT NULL,
`ask` tinyint(4) NOT NULL,
`recv` tinyint(4) NOT NULL,
`nick` varchar(255) DEFAULT NULL,
PRIMARY KEY (`rosterID`),
KEY `ofRoster_unameid_idx` (`username`),
KEY `ofRoster_jid_idx` (`jid`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ofUser` (
`username` varchar(64) NOT NULL,
`plainPassword` varchar(32) DEFAULT NULL,
`encryptedPassword` varchar(255) DEFAULT NULL,
`name` varchar(100) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`creationDate` char(15) NOT NULL,
`modificationDate` char(15) NOT NULL,
PRIMARY KEY (`username`),
KEY `ofUser_cDate_idx` (`creationDate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
delimiter ;;
CREATE TRIGGER `UpdateNickOnInsert` BEFORE INSERT ON `ofRoster` FOR EACH ROW BEGIN
SET NEW.nick=(SELECT name FROM ofUser where username=NEW.username);
END
;;
delimiter ;
delimiter ;;
CREATE TRIGGER `UpdateRosterNicksOnUpdate` AFTER UPDATE ON `ofUser` FOR EACH ROW BEGIN
IF NEW.name <> OLD.name
THEN
UPDATE ofRoster r SET r.nick=NEW.name WHERE r.username=OLD.username;
END IF;
END
;;
delimiter ;

Mysql statement insert, if inserted, insert another

I have the following statement:
INSERT INTO `Properties`(`Id`, `Url`, `BrokerId`, `LastFound`) VALUES
(#Id,#Url,#BrokerId,#LastFound)
ON DUPLICATE KEY UPDATE LastFoundOn = #LastFoundOn;
INSERT INTO `Events`(`Id`, `Type`, `DateTime`, `PropertyId`) VALUES
(#EventId,#EventType,#Now,#Id);
There is a foreign key constraint between Properties.Id and Events.PropertyId. And the Url is unique.
This works - almost. When a recod is not inserted, but updated because of duplicate key (Url), then the insert into event will fail, because the foreign key simply doesn't exist. Like this:
Eg:
exists: 1 | http://test1.com | 2 | 2013-03-13
to insert: 2 | http://test2.com | 2 | 2013-03-14
When trying to insert, it updates instead, because of the unique url. When afterwards trying to insert the event, a foreign key (2) doesn't exist in the Properties table. How can I make an if then statement to handle this scenario?
Something like (?):
INSERT INTO `Properties`(`Id`, `Url`, `BrokerId`, `LastFound`) VALUES
(#Id,#Url,#BrokerId,#LastFound)
ON DUPLICATE KEY UPDATE LastFoundOn = #LastFoundOn;
IF LastInserted = #Id THEN
INSERT INTO `Events`(`Id`, `Type`, `DateTime`, `PropertyId`) VALUES
(#EventId,#EventType,#Now,#Id);
END IF;
UPDATE:
A trigger might be the solution, but I'm struggeling making it work. What's wrong here?
DELIMITER $$
CREATE TRIGGER Event_Submitted_Trigger AFTER INSERT ON Properties
FOR EACH ROW
BEGIN
INSERT INTO Events VALUES(SELECT(UUID()), 'PropertySubmitted', SELECT(NOW()), new.Id);
END$$
I get the following error: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT(NOW()), new.Id); END$$' at line 4
Best regards,
Søren
UPDATE:
Here is my schema:
CREATE TABLE IF NOT EXISTS `Events` (
`Id` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Type` enum('PropertySubmitted','PropertyChanged','PropertyRemoved') NOT NULL,
`DateTime` datetime NOT NULL,
`Attribute` varchar(128) NOT NULL,
`From` varchar(512) NOT NULL,
`To` varchar(512) NOT NULL,
`PropertyId` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`Id`),
KEY `IX_FK_PropertyEvent` (`PropertyId`),
KEY `DateTimeIndex` (`DateTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `Properties`
--
CREATE TABLE IF NOT EXISTS `Properties` (
`Id` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Url` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Type` varchar(64) NOT NULL,
`ExtractedAddress` varchar(192) NOT NULL,
`ExtractedPostcode` varchar(8) NOT NULL,
`ExtractedCity` varchar(64) NOT NULL,
`StreetName` varchar(128) DEFAULT NULL,
`StreetNumber` varchar(8) DEFAULT NULL,
`Floor` varchar(8) DEFAULT NULL,
`Side` varchar(8) DEFAULT NULL,
`DoorNo` varchar(8) DEFAULT NULL,
`Postcode` int(4) DEFAULT NULL,
`City` varchar(64) DEFAULT NULL,
`Latitude` double DEFAULT NULL,
`Longitude` double DEFAULT NULL,
`ImageUrl` varchar(512) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`Price` int(8) NOT NULL,
`Payout` int(8) NOT NULL,
`GrossPrice` int(6) NOT NULL,
`NetPrice` int(6) NOT NULL,
`Area` int(5) NOT NULL,
`GroundArea` int(5) NOT NULL,
`Rooms` int(2) NOT NULL,
`Year` int(4) NOT NULL,
`PriceChange` int(11) NOT NULL,
`FirstFoundOn` datetime NOT NULL,
`SubmittedOn` datetime NOT NULL,
`LastFoundOn` datetime NOT NULL,
`FoundAt` varchar(256) DEFAULT NULL,
`Validated` tinyint(1) NOT NULL,
`BrokerId` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`Archived` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`Id`),
UNIQUE KEY `Url` (`Url`),
KEY `IX_FK_PropertyBroker` (`BrokerId`),
KEY `UrlIndex` (`Url`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Triggers `Properties`
--
DROP TRIGGER IF EXISTS `Event_Submitted_Trigger`;
DELIMITER //
CREATE TRIGGER `Event_Submitted_Trigger` AFTER INSERT ON `Properties`
FOR EACH ROW BEGIN
INSERT INTO `Events` VALUES(UUID(), 'PropertySubmitted', NOW(), NEW.Id);
END
//
DELIMITER ;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `Events`
--
ALTER TABLE `Events`
ADD CONSTRAINT `Events_ibfk_1` FOREIGN KEY (`PropertyId`) REFERENCES `Properties` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Constraints for table `Properties`
--
ALTER TABLE `Properties`
ADD CONSTRAINT `Properties_ibfk_2` FOREIGN KEY (`BrokerId`) REFERENCES `Brokers` (`Id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
Assuming the following structure:
CREATE TABLE Properties (
id INT,
url VARCHAR(100),
lastFound DATETIME,
UNIQUE (url)
) ;
CREATE TABLE Events (
id VARCHAR(36),
type VARCHAR(20),
t DATETIME,
propertyId INT
) ;
Here is a working trigger:
DELIMITER $$
CREATE TRIGGER Event_Submitted_Trigger AFTER INSERT ON Properties
FOR EACH ROW BEGIN
INSERT INTO Events VALUES( UUID(), 'PropertySubmitted', NOW(), new.Id);
END $$
DELIMITER ;
See it in action here. Notice the NOW()+SLEEP(1) hack, only meant to delay execution in order to get a significant result (SLEEP() returns 0 if not interrupted).

Help with MySQL Query with many Joins

Setup: Contact database using 4 tables
Contacts
Cities
States
Zips
Structure:
CREATE TABLE `contacts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`first` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`prefix` varchar(50) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`suffix` varchar(50) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`address` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`address_1` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`city_id` int(100) DEFAULT NULL,
`state_id` int(20) DEFAULT NULL,
`alt_address_1` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_address_2` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_city` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_state` varchar(20) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`alt_zip` varchar(15) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`publish_name` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`salutation` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`mail_label` varchar(255) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`solicitor` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`is_volunteer` tinyint(1) DEFAULT NULL,
`is_sponsor` tinyint(1) DEFAULT '0',
`is_company` tinyint(1) DEFAULT '0',
`is_foundation` tinyint(1) DEFAULT '0',
`status` varchar(15) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`created_on` datetime NOT NULL,
`created_by` varchar(30) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`modified_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified_by` varchar(100) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`agency_id` int(25) DEFAULT NULL,
`primary_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `primary_id` (`primary_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3008 DEFAULT CHARSET=utf8
CREATE TABLE `cities` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`city` varchar(50) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`stateid` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `city` (`city`)
) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=utf8
CREATE TABLE `states` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`abbreviation` varchar(2) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`state` varchar(20) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `state` (`state`),
UNIQUE KEY `abbreviation` (`abbreviation`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=52 DEFAULT CHARSET=utf8
CREATE TABLE `zips` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`zip` varchar(10) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`cityid` int(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `zip` (`zip`)
) ENGINE=InnoDB AUTO_INCREMENT=128 DEFAULT CHARSET=utf8
I have filled the contacts with 111 contacts, the states are simply all of the states, and cities have corresponding id keys that relate to the state id, zip codes have a key to match to a city.
The query is to generate a list of people to match up to the proper fields. Here is the query.
SELECT concat(contacts.last,' ', contacts.first) as name
, cities.city
, zips.zip
FROM contacts
JOIN cities
ON cities.id = contacts.city_id
JOIN states ON states.id = contacts.state_id
JOIN zips ON zips.cityid = cities.id
This query, return 338 rows, of a possible 11 contacts. There obvious duplicates. This happens when I join zip codes, which because they belong to more than 1 city, it gets matched for each city (I think thats what is happening). Anyone have an answer on how to properly join these tables?
Thank you.
Rich
I believe that you should re-think the surrogate key usage on a lot of these tables and use natural keys where possible. Taking the state table for an example, in most cases it will be acceptable to simply use the state short (ie. TX vs. Texas) for data and display purposes. This means that if you removed the incrementing ID on the states table and used a natural key for each state, you would reduce the necessecity of a join in 90% of cases.
Then use state.abbriviation as the FK in tables that need to store state values. Extending this to zipcodes and cities, you can FK the state abbr to the city table, and make a compound FK form the cities table to the contacts table giving you a key for both the city and the state at the same time.
Example schema (excluded zipcodes table and shortened contacts table):
CREATE TABLE IF NOT EXISTS `states` (
`state_id` CHAR(2) NOT NULL ,
`name` VARCHAR(45) NULL ,
PRIMARY KEY (`state_id`) ,
UNIQUE INDEX `state_name` (`name` ASC)
)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `cities` (
`state_id` CHAR(2) NOT NULL ,
`city_name` VARCHAR(255) NOT NULL ,
PRIMARY KEY (`state_id`, `city_name`) ,
INDEX `fk_city_state_id` (`state_id` ASC) ,
CONSTRAINT `fk_city_state_id`
FOREIGN KEY (`state_id` )
REFERENCES `states` (`state_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `contacts` (
`contacts_id` INT NOT NULL AUTO_INCREMENT ,
`state` CHAR(2) NULL ,
`city` VARCHAR(255) NULL ,
PRIMARY KEY (`contacts_id`) ,
INDEX `fk_contact_city` (`state` ASC, `city` ASC) ,
INDEX `fk_contact_state` (`state` ASC) ,
CONSTRAINT `fk_contact_city`
FOREIGN KEY (`state` , `city` )
REFERENCES `cities` (`state_id` , `city_name` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_contact_state`
FOREIGN KEY (`state` )
REFERENCES `states` (`state_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION
)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Data for table `states`
-- -----------------------------------------------------
SET AUTOCOMMIT=0;
INSERT INTO `states` (`state_id`, `name`) VALUES ('TX', 'Texas');
INSERT INTO `states` (`state_id`, `name`) VALUES ('CA', 'California');
INSERT INTO `states` (`state_id`, `name`) VALUES ('OR', 'Oregon');
COMMIT;
-- -----------------------------------------------------
-- Data for table `cities`
-- -----------------------------------------------------
SET AUTOCOMMIT=0;
INSERT INTO `cities` (`state_id`, `city_name`) VALUES ('CA', 'modesto');
INSERT INTO `cities` (`state_id`, `city_name`) VALUES ('OR', 'protland');
INSERT INTO `cities` (`state_id`, `city_name`) VALUES ('TX', 'Dallas');
COMMIT;
Now your query is simplified except in the extreme case where you'd need a full state nomenclature:
SELECT
concat(contacts.last,' ', contacts.first) as name,
city,
state,
zip
FROM contacts
WHERE {INSERTWHERE}
your tables a properly joined. i think the problem you have here is that you have normalized your data improperly and gone too far. just store the address as provided. don't try and split it in to table with numeric ID's.
for example, what possible benefit do you get by storing the state as a number in the contact table instead of just the state code? and the same question applies to city.