How can I get the AUTO_INCREMENT value in Sequel? - mysql

In MySQL, I can get the auto-increment value by:
SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'DatabaseName'
AND TABLE_NAME = 'TableName';
How do I query this information in Sequel? When I tried DB.run and DB.get, it didn't seem to work.

If nothing else, Sequel makes it easy to send raw SQL:
DB["SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'DatabaseName' AND TABLE_NAME = 'TableName'"]
From the documentation:
Using raw SQL
DB.run "CREATE TABLE users (name VARCHAR(255) NOT NULL, age INT(3) NOT NULL)"
dataset = DB["SELECT age FROM users WHERE name = ?", name]
dataset.map(:age)
DB.fetch("SELECT name FROM users") do |row|
p row[:name]
end

Related

How to check if the table exists before inserting data?

How to make such as: IF (table if exists types) THEN ... END ?
Try this:
SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = '[database name]'
AND table_name = '[table name]';
Save the result and you can use it in an if statement

How to search for truncated data with the original data in MySQL

Here is a database structure to illustrate my question
CREATE TABLE `company` (
`company_id` int(11) NOT NULL,
`name` varchar(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
When I add a company that has a name longer than 10 characters it will be truncated. So when I search the company with its full name I cannot find it.
Question: How can I get the maximum length of the « name » column wich is 10 in this example to be able to truncate and do the research with « SUBSTRING() »
NB : The context doesn’t permit to change the maximum length of the
name
The best way to do this is by querying the information_schema. Something like this should work for you.
select character_maximum_length
from information_schema.columns
where table_schema = database()
and table_name = 'company'
and column_name = 'name'
You'll get a one row resultset with the length you want.
You can make this into part of your query with a (nasty!) query pattern like this.
select company_id, name
from company
where name = substring('A long search string', 1, (
select character_maximum_length
from information_schema.columns
where table_schema = database()
and table_name = 'company'
and column_name = 'name') )
Or you could try this (more readable) consecutive pair of queries using a session variable.
select #max := character_maximum_length
from information_schema.columns
where table_schema = database()
and table_name = 'hotels'
and column_name = 'name' ;
select company_id, name
from company
where name = substring('A long search string', 1, #max)
You mean you're searching something like
SELECT * FROM company WHERE company = LEFT('something longer than 10 chars', 10);
?
LEFT() documentation
To get the length of a varchar column you have to query the information_schema.
SELECT character_maximum_length
FROM information_schema.columns
WHERE table_schema = 'your_schema'
AND table_name = 'company'
AND column_name = 'name';
So your query becomes
SELECT *
FROM company
WHERE company = LEFT('something longer than 10 chars', (
SELECT character_maximum_length
FROM information_schema.columns
WHERE table_schema = 'your_schema'
AND table_name = 'company'
AND column_name = 'name';
)
);

Select auto_increment field value

I'm trying to compare the auto increment field value of the current table with a constant value, the method I tried is below query:
WHERE (SELECT column_name FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name='clients') = '1'
It won't show any output, Is there anything wrong with it?
WHERE (SELECT AUTO_INCREMENT FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name='clients') = <your number>
You should try something like above

Get current AUTO_INCREMENT value for any table

How do I get the current AUTO_INCREMENT value for a table in MySQL?
You can get all of the table data by using this query:
SHOW TABLE STATUS FROM `DatabaseName` WHERE `name` LIKE 'TableName' ;
You can get exactly this information by using this query:
SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'DatabaseName'
AND TABLE_NAME = 'TableName';
If you just want to know the number, rather than get it in a query then you can use:
SHOW CREATE TABLE tablename;
You should see the auto_increment at the bottom
I believe you're looking for MySQL's LAST_INSERT_ID() function. If in the command line, simply run the following:
LAST_INSERT_ID();
You could also obtain this value through a SELECT query:
SELECT LAST_INSERT_ID();
Even though methai's answer is correct if you manually run the query, a problem occurs when 2 concurrent transaction/connections actually execute this query at runtime in production (for instance).
Just tried manually in MySQL workbench with 2 connections opened simultaneously:
CREATE TABLE translation (
id BIGINT PRIMARY KEY AUTO_INCREMENT
);
# Suppose we have already 20 entries, we execute 2 new inserts:
Transaction 1:
21 = SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'DatabaseName' AND TABLE_NAME = 'translation';
insert into translation (id) values (21);
Transaction 2:
21 = SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'DatabaseName' AND TABLE_NAME = 'translation';
insert into translation (id) values (21);
# commit transaction 1;
# commit transaction 2;
Insert of transaction 1 is ok
Insert of transaction 2 goes in error: Error Code: 1062. Duplicate entry '21' for key 'PRIMARY'.
A good solution would be jvdub's answer because per transaction/connection the 2 inserts will be:
Transaction 1:
insert into translation (id) values (null);
21 = SELECT LAST_INSERT_ID();
Transaction 2:
insert into translation (id) values (null);
22 = SELECT LAST_INSERT_ID();
# commit transaction 1;
# commit transaction 2;
But we have to execute the last_insert_id() just after the insert!
And we can reuse that id to be inserted in others tables where a foreign key is expected!
Also, we cannot execute the 2 queries as following:
insert into translation (id) values ((SELECT AUTO_INCREMENT FROM
information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()
AND TABLE_NAME='translation'));
because we actually are interested to grab/reuse that ID in other table or to return!
EDIT: 02/08/2021, Retrieving the value
To actually retrieve the value in the application (example done in Java with MyBatis):
#Mapper
public interface ClientMapper {
#Select("select last_insert_id()")
Long getLastInsertedId();
#Insert({...})
void insertClientInfo(ClientInfo client);
}
And then in Repository
public void insertClientInfo(ClientInfo clientInfo) {
mapper.insertClientInfo(clientInfo);
Long pk = mapper.getLastInsertedId();
clientInfo.setId(pk);
}
mysqli executable sample code:
<?php
$db = new mysqli("localhost", "user", "password", "YourDatabaseName");
if ($db->connect_errno) die ($db->connect_error);
$table=$db->prepare("SHOW TABLE STATUS FROM YourDatabaseName");
$table->execute();
$sonuc = $table->get_result();
while ($satir=$sonuc->fetch_assoc()){
if ($satir["Name"]== "YourTableName"){
$ai[$satir["Name"]]=$satir["Auto_increment"];
}
}
$LastAutoIncrement=$ai["YourTableName"];
echo $LastAutoIncrement;
?>
Query to check percentage "usage" of AUTO_INCREMENT for all tables of one given schema (except columns with type bigint unsigned):
SELECT
c.TABLE_NAME,
c.COLUMN_TYPE,
c.MAX_VALUE,
t.AUTO_INCREMENT,
IF (c.MAX_VALUE > 0, ROUND(100 * t.AUTO_INCREMENT / c.MAX_VALUE, 2), -1) AS "Usage (%)"
FROM
(SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_TYPE,
CASE
WHEN COLUMN_TYPE LIKE 'tinyint(1)' THEN 127
WHEN COLUMN_TYPE LIKE 'tinyint(1) unsigned' THEN 255
WHEN COLUMN_TYPE LIKE 'smallint(%)' THEN 32767
WHEN COLUMN_TYPE LIKE 'smallint(%) unsigned' THEN 65535
WHEN COLUMN_TYPE LIKE 'mediumint(%)' THEN 8388607
WHEN COLUMN_TYPE LIKE 'mediumint(%) unsigned' THEN 16777215
WHEN COLUMN_TYPE LIKE 'int(%)' THEN 2147483647
WHEN COLUMN_TYPE LIKE 'int(%) unsigned' THEN 4294967295
WHEN COLUMN_TYPE LIKE 'bigint(%)' THEN 9223372036854775807
WHEN COLUMN_TYPE LIKE 'bigint(%) unsigned' THEN 0
ELSE 0
END AS "MAX_VALUE"
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE EXTRA LIKE '%auto_increment%'
) c
JOIN INFORMATION_SCHEMA.TABLES t ON (t.TABLE_SCHEMA = c.TABLE_SCHEMA AND t.TABLE_NAME = c.TABLE_NAME)
WHERE
c.TABLE_SCHEMA = 'YOUR_SCHEMA'
ORDER BY
`Usage (%)` DESC;
I was looking for the same and ended up by creating a static method inside a Helper class (in my case I named it App\Helpers\Database).
The method
/**
* Method to get the autoincrement value from a database table
*
* #access public
*
* #param string $database The database name or configuration in the .env file
* #param string $table The table name
*
* #return mixed
*/
public static function getAutoIncrementValue($database, $table)
{
$database ?? env('DB_DATABASE');
return \DB::select("
SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '" . env('DB_DATABASE') . "'
AND TABLE_NAME = '" . $table . "'"
)[0]->AUTO_INCREMENT;
}
To call the method and get the MySql AUTO_INCREMENT just use the following:
$auto_increment = \App\Helpers\Database::getAutoIncrementValue(env('DB_DATABASE'), 'your_table_name');
Hope it helps.
If column is autoincremented in sql server then to see the current autoincremented value, and if you want to edit that value for that column use the following query.
-- to get current value
select ident_current('Table_Name')
-- to update current value
dbcc checkident ('[Table_Name]',reseed,"Your Value")
list dbname all tabename and AUTO_INCREMENT
SELECT `AUTO_INCREMENT`,`TABLE_NAME`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbname' ORDER BY AUTO_INCREMENT desc

How to check if an index exists on a table field in MySQL

How do I check if an index exists on a table field in MySQL?
I've needed to Google this multiple times, so I'm sharing my Q/A.
Use SHOW INDEX like so:
SHOW INDEX FROM [tablename]
Docs: https://dev.mysql.com/doc/refman/5.0/en/show-index.html
Try:
SELECT * FROM information_schema.statistics
WHERE table_schema = [DATABASE NAME]
AND table_name = [TABLE NAME] AND column_name = [COLUMN NAME]
It will tell you if there is an index of any kind on a certain column without the need to know the name given to the index. It will also work in a stored procedure (as opposed to show index)
show index from table_name where Column_name='column_name';
SHOW KEYS FROM tablename WHERE Key_name='unique key name'
will show if a unique key exists in the table.
Use the following statement:
SHOW INDEX FROM *your_table*
And then check the result for the fields: row["Table"], row["Key_name"]
Make sure you write "Key_name" correctly
To look at a table's layout from the CLI, you would use
desc mytable
or
show table mytable
Adding to what GK10 suggested:
Use the following statement: SHOW INDEX FROM your_table
And then check the result for the fields: row["Table"],
row["Key_name"]
Make sure you write "Key_name" correctly
One can take that and work it into PHP (or other language) wrapped around an sql statement to find the index columns. Basically you can pull in the result of SHOW INDEX FROM 'mytable' into PHP and then use the column 'Column_name' to get the index column.
Make your database connection string and do something like this:
$mysqli = mysqli_connect("localhost", "my_user", "my_password", "world");
$sql = "SHOW INDEX FROM 'mydatabase.mytable' WHERE Key_name = 'PRIMARY';" ;
$result = mysqli_query($mysqli, $sql);
while ($row = $result->fetch_assoc()) {
echo $rowVerbatimsSet["Column_name"];
}
Try to use this:
SELECT TRUE
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = "{DB_NAME}"
AND TABLE_NAME = "{DB_TABLE}"
AND COLUMN_NAME = "{DB_INDEXED_FIELD}";
You can use the following SQL to check whether the given column on table was indexed or not:
select a.table_schema, a.table_name, a.column_name, index_name
from information_schema.columns a
join information_schema.tables b on a.table_schema = b.table_schema and
a.table_name = b.table_name and
b.table_type = 'BASE TABLE'
left join (
select concat(x.name, '/', y.name) full_path_schema, y.name index_name
FROM information_schema.INNODB_SYS_TABLES as x
JOIN information_schema.INNODB_SYS_INDEXES as y on x.TABLE_ID = y.TABLE_ID
WHERE x.name = 'your_schema'
and y.name = 'your_column') d on concat(a.table_schema, '/', a.table_name, '/', a.column_name) = d.full_path_schema
where a.table_schema = 'your_schema'
and a.column_name = 'your_column'
order by a.table_schema, a.table_name;
Since the joins are against INNODB_SYS_*, the match indexes only came from the INNODB tables only.
If you need to check if a index for a column exists as a database function, you can use/adopt this code.
If you want to check if an index exists at all regardless of the position in a multi-column-index, then just delete the part AND SEQ_IN_INDEX = 1.
DELIMITER $$
CREATE FUNCTION `fct_check_if_index_for_column_exists_at_first_place`(
`IN_SCHEMA` VARCHAR(255),
`IN_TABLE` VARCHAR(255),
`IN_COLUMN` VARCHAR(255)
)
RETURNS tinyint(4)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT 'Check if index exists at first place in sequence for a given column in a given table in a given schema. Returns -1 if schema does not exist. Returns -2 if table does not exist. Returns -3 if column does not exist. If index exists in first place it returns 1, otherwise 0.'
BEGIN
-- Check if index exists at first place in sequence for a given column in a given table in a given schema.
-- Returns -1 if schema does not exist.
-- Returns -2 if table does not exist.
-- Returns -3 if column does not exist.
-- If the index exists in first place it returns 1, otherwise 0.
-- Example call: SELECT fct_check_if_index_for_column_exists_at_first_place('schema_name', 'table_name', 'index_name');
-- check if schema exists
SELECT
COUNT(*) INTO #COUNT_EXISTS
FROM
INFORMATION_SCHEMA.SCHEMATA
WHERE
SCHEMA_NAME = IN_SCHEMA
;
IF #COUNT_EXISTS = 0 THEN
RETURN -1;
END IF;
-- check if table exists
SELECT
COUNT(*) INTO #COUNT_EXISTS
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = IN_SCHEMA
AND TABLE_NAME = IN_TABLE
;
IF #COUNT_EXISTS = 0 THEN
RETURN -2;
END IF;
-- check if column exists
SELECT
COUNT(*) INTO #COUNT_EXISTS
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = IN_SCHEMA
AND TABLE_NAME = IN_TABLE
AND COLUMN_NAME = IN_COLUMN
;
IF #COUNT_EXISTS = 0 THEN
RETURN -3;
END IF;
-- check if index exists at first place in sequence
SELECT
COUNT(*) INTO #COUNT_EXISTS
FROM
information_schema.statistics
WHERE
TABLE_SCHEMA = IN_SCHEMA
AND TABLE_NAME = IN_TABLE AND COLUMN_NAME = IN_COLUMN
AND SEQ_IN_INDEX = 1;
IF #COUNT_EXISTS > 0 THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END$$
DELIMITER ;
You can't run a specific show index query because it will throw an error if an index does not exist. Therefore, you have to grab all indexes into an array and loop through them if you want to avoid any SQL errors.
Heres how I do it. I grab all of the indexes from the table (in this case, leads) and then, in a foreach loop, check if the column name (in this case, province) exists or not.
$this->name = 'province';
$stm = $this->db->prepare('show index from `leads`');
$stm->execute();
$res = $stm->fetchAll();
$index_exists = false;
foreach ($res as $r) {
if ($r['Column_name'] == $this->name) {
$index_exists = true;
}
}
This way you can really narrow down the index attributes. Do a print_r of $res in order to see what you can work with.