I am trying to run a CREATE TABLE script which has multiple INDEXES.
CREATE TABLE IF NOT EXISTS Equipment (
EquipmentID BIGINT UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT,
Type VARCHAR(255) NOT NULL,
Make VARCHAR(255),
Model VARCHAR(255),
Description VARCHAR(255),
OperationNotes TEXT,
Damaged BOOLEAN DEFAULT 0,
PRIMARY KEY (EquipmentID),
INDEX ('EquipmentID'),
INDEX('Type'),
INDEX('Model'),
INDEX('Description')
INDEX('Damaged')
);
However I get a syntax error:
"(" is not valid at this position for this server version
On line:
INDEX ('EquipmentID'),
Single quote (') denote string literals. When referring to object names (such as columns), you shouldn't use single quotes. Remove them, and you should be OK. Also, note that a primary key implicitly creates an index, so you don't need to explicitly create an index on EquipmentID:
CREATE TABLE IF NOT EXISTS Equipment (
EquipmentID BIGINT UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT,
Type VARCHAR(255) NOT NULL,
Make VARCHAR(255),
Model VARCHAR(255),
Description VARCHAR(255),
OperationNotes TEXT,
Damaged BOOLEAN DEFAULT 0,
PRIMARY KEY (EquipmentID),
INDEX (Type),
INDEX (Model),
INDEX (Description),
INDEX (Damaged)
);
Related
I have a database. As you can see the primary key is an auto_increment and is also unique. I read that publically sharing a row's primary key of a table to the public is unsafe. I want to assign each row in customers a unique ID that I can publically share. How can I do this without having to specify each time what the public_id is in the INSERT statement? The database should automatically find a unique ID to assign to that row just like it does for id because of auto_increment.
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
-- public_id (an ID I can give to the public to uniquely identify this row
);
INSERT INTO customers (name) VALUES ('Bob'), ('Sarah'), ('Bob');
Well, here's one way:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(36) not null unique default uuid()
);
Note that the manual says:
Warning
Although UUID() values are intended to be unique, they are not necessarily unguessable or unpredictable. If unpredictability is required, UUID values should be generated some other way.
So this is simple, and maybe will float your goat, but we can also try better:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(24) not null unique default to_base64(random_bytes(18))
);
This will be a nice and dense identifier, but it will have characters + and / which don't play well with URLs. You can encode them, of course, but if you want to go one lazier, you can also do this:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(32) not null unique default hex(random_bytes(16))
);
Mind you, the identifier will get quite a bit longer this way.
To get the best of both worlds, we can do this, at the expense of a really long default value:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(24) not null unique default replace(replace(to_base64(random_bytes(18)), '+', '_'), '/', '-')
);
Also note that messing around with MD5()/SHA()/SHA1()/SHA2() is no better than just generating a random hex string with a given length.
I'm trying to create a table that contains indexed virtual columns that are referencing a JSON.
I've created the table which contains a virtual column named "amount". The problem is that the JSON doesn't always contain the key "amount". Sometimes it's named "presentationAmount".
Is it possible to put a condition in place for this?
When the JSON contains the key "threeDSecure" that's when "presentationAmount" is used, otherwise "amount" is used.
Here's my create table code:
CREATE TABLE transactions (
id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
json JSON DEFAULT NULL,
type VARCHAR(12) GENERATED ALWAYS AS (json->>"$.transaction.type"),
uuid VARCHAR(32) GENERATED ALWAYS AS (json->>"$.transaction.payload.id"),
holder VARCHAR(20) GENERATED ALWAYS AS (json->>"$.transaction.payload.card.holder"),
amount DECIMAL(11,2) GENERATED ALWAYS AS (json->>"$.transaction.payload.amount"),
resultCode VARCHAR(11) GENERATED ALWAYS AS (json->>"$.transaction.payload.result.code"),
processingTime DATETIME GENERATED ALWAYS AS (json->>"$.transaction.payload.timestamp"),
paymentType VARCHAR(2) GENERATED ALWAYS AS (json->>"$.transaction.payload.paymentType"),
paymentBrand VARCHAR(20) GENERATED ALWAYS AS (json->>"$.transaction.payload.paymentBrand"),
eci INT(2) GENERATED ALWAYS AS (json->>"$.transaction.payload.eci"),
recurringType VARCHAR(9) GENERATED ALWAYS AS (json->>"$.transaction.payload.recurringType"),
clearingInstitute VARCHAR(30) GENERATED ALWAYS AS (json->>"$.transaction.payload.resultDetails.clearingInstituteName"),
merchantTransactionId VARCHAR(64) GENERATED ALWAYS AS (json->>"$.transaction.payload.merchantTransactionId"),
divisionName VARCHAR(32) GENERATED ALWAYS AS (json->>"$.division.name"),
divisionUuid VARCHAR(32) GENERATED ALWAYS AS (json->>"$.division.uuid"),
merchantName VARCHAR(32) GENERATED ALWAYS AS (json->>"$.merchant.name"),
merchantUuid VARCHAR(32) GENERATED ALWAYS AS (json->>"$.merchant.uuid"),
channelName VARCHAR(32) GENERATED ALWAYS AS (json->>"$.channel.name"),
channelUuid VARCHAR(32) GENERATED ALWAYS AS (json->>"$.channel.uuid"),
INDEX typeIndex (type),
INDEX idIndex (uuid),
INDEX holderIndex (holder),
INDEX amountIndex (amount),
INDEX resultCodeIndex (resultCode),
INDEX timestampIndex (processingTime),
INDEX paymentTypeIndex (paymentType),
INDEX paymentBrandIndex (paymentBrand),
INDEX recurringTypeIndex (recurringType),
INDEX clearingInstituteIndex (clearingInstitute),
INDEX merchantTransactionIdIndex (merchantTransactionId),
INDEX divisonNameIndex (divisionName),
INDEX divisionUuidIndex (divisionUuid),
INDEX merchantNameIndex (merchantName),
INDEX merchantUuidindex (merchantUuid),
INDEX channelNameIndex (channelName),
INDEX channelUuidIndex (channelUuid)
) ENGINE=INNODB;
You can use an IF() expression.
amount DECIMAL(11,2) GENERATED ALWAYS AS
(IF(JSON_CONTAINS_PATH(json, 'one', '$.transaction.payload.threeDSecure'),
json->>"$.transaction.payload.presentationAmount",
json->>"$.transaction.payload.amount")),
See the documentation of JSON_CONTAINS_PATH() for details of its use.
I'm having some problems with this piece of mySQL code that is not wanting to get fixed
CREATE TABLE `DatabaseMGR`
(
`databaseID` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`primCat` INT UNSIGNED NOT NULL,
`databaseName` VARCHAR(20),
UNIQUE KEY (`databaseID`),
PRIMARY KEY (`databaseID`),
INDEX `databaseID`
)ENGINE = InnoDB;
It says that there is an error at line 1 with the regular "check your mysql syntax for right usage" error in response to ` usage. Is there something I'm missing? I'm new to sql so I might be missing something obvious.
Thanks.
The main point for your problem is at the line you are defining the index. In create table statement, you should use it with this syntax:
create table table_name (
...
index `INDEX_NAME` (`INDEX_COLUMN`)
);
So you can fix your problem by changing your code to below:
CREATE TABLE `DatabaseMGR`
(
`databaseID` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`primCat` INT UNSIGNED NOT NULL,
`databaseName` VARCHAR(20),
UNIQUE KEY (`databaseID`),
PRIMARY KEY (`databaseID`),
INDEX `ix_databaseID` (`databaseID`) # Note the change on this line
)ENGINE = InnoDB;
However, in MySQL primary key column gets an index by default, so you can leave out that line totally, that results in the following code:
CREATE TABLE `DatabaseMGR`
(
`databaseID` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`primCat` INT UNSIGNED NOT NULL,
`databaseName` VARCHAR(20),
UNIQUE KEY (`databaseID`),
PRIMARY KEY (`databaseID`)
)ENGINE = InnoDB;
To improve more:
databaseID is already a primary key, so you do not have to make define it unique again, since: primary key = unique + not null
Since MySQL is case insensitive, you should not use camel case names. So instead of databaseID, better to say database_id. There are more naming convention you can go through, though I will not mention here.
So for final table defination I suggest:
CREATE TABLE `database_mgr`
(
`database_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`prim_cat` INT UNSIGNED NOT NULL,
`database_name` VARCHAR(20),
PRIMARY KEY (`databaseID`)
)ENGINE = InnoDB;
How can I give the long text as a table field name in mysql?
Here is what I tried:
CREATE TABLE IF NOT EXISTS surveyForm_8(
surveyForm_8_id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(surveyForm_8_id),
survey_form_id VARCHAR(255),
submitted_by VARCHAR(15),
submitted_on TIMESTAMP,
'How_to_change_the_way_of_road?' VARCHAR(255)
)
But I got this error:
#1059 error
Try this one, you should use the ` symbol for column names
CREATE TABLE IF NOT EXISTS surveyForm_8(surveyForm_8_id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(surveyForm_8_id), survey_form_id varchar(255) ,submitted_by varchar(15),
submitted_on timestamp, `How_to_change_the_way_of_road?` varchar(255));
Please see http://dev.mysql.com/doc/refman/5.5/en/identifiers.html for valid table and field names.
Basically, double quotes only work in ANSI_QUOTES mode. The default is to use `backticks` to quote. Also, the maximum length of table / field names is 64 characters.
I am using a VARCHAR as my primary key. I want to auto increment it (base 62, lower/upper case, numbers), However, the below code fails (for obvious reasons):
CREATE TABLE IF NOT EXISTS `campaign` (
`account_id` BIGINT(20) NOT NULL,
`type` SMALLINT(5) NOT NULL,
`id` VARCHAR(16) NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
however, this works:
CREATE TABLE IF NOT EXISTS `campaign` (
`account_id` BIGINT(20) NOT NULL,
`type` SMALLINT(5) NOT NULL,
`id` VARCHAR(16) NOT NULL PRIMARY KEY
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
What is the best way to keep track of incrementation of 'id' myself? (Since auto_increment doesn't work). Do i need to make another table that contains the current iteration of ID? Or is there a better way to do this?
EDIT: I want to clarify that I know that using INT is a auto_increment primary key is the logical way to go. This question is in response to some previous dialogue I saw. Thanks
you have to use an INT field
and translate it to whatever format you want at select time
example of a solution to your problem:
create a file with a unique number and then increment with a function.
the filename can be the prefix and the file binary content represent a number.
when you need a new id to the reg invoque the function
Example
String generateID(string A_PREFIX){
int id_value = parsetoInt(readFile(A_PREFIX).getLine())
int return_id_value = id_value++
return return_id_value
}
where "A_PREFIX-" is the file name wich you use to generate the id for the field.
Or just create a sequence and maintain the pk field using the sequence to generate the primary key value with nextval function. And if perf is an issue, use cache on sequence.
But as others have stated, this is sub-optimal, if your primary key contains a numbered sequence then it's better to use int and auto-increment.
I don't see a use case where pk has to auto-increment but be a varchar data type, it doesn't make sense.
Assuming that for reasons external to the database, you do need that varchar column, and it needs to autoIncrement, then how about creating a trigger that grabs the existing autoIncrement value and uses Convert() to convert that value into a VarChar, dropping the VarChar into the field of interest. As mentioned in a previous answer, you could concatenate the table-name with the new varChar value, if there is some advantage to that.