JDBI ALTER TABLE DROP PARTITION - mysql

Hey I'm having an issue with altering table partitions using JDBI. Here is an example of the query I'm trying to run:
ALTER TABLE table1 DROP PARTITION P_1
This runs fine in MySQL when dropping the partition "P_1" from the table "table1."
I've implemented it in my java code as the following:
#SqlUpdate("ALTER TABLE table1 DROP PARTITION :partition;")
public void deletePartition(#Bind("partition") String partition);
And call this function as such
deletePartition("P_1")
However, this results in the following error:
Causing: org.skife.jdbi.v2.exceptions.UnableToExecuteStatementException: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 ''P_1'' at line 1 [statement:"ALTER TABLE table1 DROP PARTITION :partition;", located:"ALTER TABLE table1 DROP PARTITION :partition;", rewritten:"/* HiveDropBoxDBI.deletePartition */ ALTER TABLE table1 DROP PARTITION ?;", arguments:{ positional:{}, named:{partition:'P_1'}, finder:[]}]
Is this functionality not supported? Or am I missing something with my syntax?
Thanks

We need to use #Define for changing the query. #Bind is only for used for binding parameters (like some_field = :value).
#SqlUpdate("ALTER TABLE table1 DROP PARTITION :partition;")
public void deletePartition(#Bind("partition") String partition);

You can't use bind parameters for DDL such as CREATE, ALTER and DROP.
In order to drop your partition, you must concatenate the partition name onto the query instead.
However, taking a partition name and appending it straight into a SQL string which gets executed is a recipe for a security vulnerability. Consider some of the following:
'escaping' the partition name with backticks,
checking that the partition name contains only certain whitelisted characters (e.g. alphanumerics and underscores),
querying the INFORMATION_SCHEMA.PARTITIONS table to see if the partition you're trying to drop exists. (This might not be a good idea if there is a chance that the partition may be created or dropped between checking for its existence and dropping it. I don't know your application well enough to say whether this would be a problem.)
As JDBI relies on constant strings for #SqlUpdate annotations, you will not be able to use JDBI in this way to drop partitions, unless you only ever want to drop the same partition.

Related

Create Table in SQL where table name is from digits

When I try do next
mysql> CREATE TABLE '20181020';
sql return an error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual
that corresponds to your MariaDB server version for the right syntax to use
near ''20181020'' at line 1
How can I solve it?
You needt to wrap identifier with backticks:
CREATE TABLE `20181020`(id INT);
I propose not to do so and use proper meaningful naming. Using date as name of table suggest that it could be table-per-date antipattern.
Related article: SELECT * FROM sales + #yymm
your can also use double quote for this type of table name
CREATE TABLE "20181020" (id INT);
insert into "20181020" values(1)
But this type of naming is not standard practice
The other answers cover the solution, which is to use backticks.
Let me add that using non-standard identifiers is a bad idea. If you start naming columns as number as well, who wants to figure out the differences between 20181020.1, 20181020.1, and 20181020.1. Is it so hard to use a prefix: t_20181020?
But you don't want to do that either. Let me explain. Presumably, if you have one table called 20181020, then tomorrow you will want another table 20181021. This is a really bad database design.
You should be putting all the data into a single table, with a date column specifying the date. You can then run queries over one table to see changes over time -- for instance.
If the tables are large and you want the ability to manipulate each day separately, then you use table partitioning to store each day's worth separately. This is handy, because partitions can be archived, restored, and dropped independently of other partitions.

create autoincrement in MySQL with pre text

I have trouble for my project using mysql, i want to create Auto Increment in view table, i create sintax like this one:
SELECT
concat(#AI:= #AI + 1,`code`)
FROM
`TEST TABLE`, (SELECT #AI:=0) as `AI`
Why if i add syntax in first line like this one:
CREATE VIEW `TEST VIEW` as
I have some error :
How fix it, or other method for this?. thanks for advance!
If you were using Oracle, you would use an object called a sequence for this purpose. But, who has the money for Oracle licenses?
If you need a series of numbers and you're using the MariaDB fork, you can do
SELECT seq FROM seq_0_to_99
or some such use of the SEQUENCE engine.
If you need persistent sequence numbers in MySQL, here's a workaround. It's a kludge: If you create the following table:
CREATE TABLE sequence ( /*MySQL*/
sequence_id BIGINT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sequence_id`)
)
Then issue these three queries one after the other:
INSERT INTO sequence () VALUES (); /*MySQL*/
DELETE FROM sequence WHERE sequence_id < LAST_INSERT_ID();
SELECT LAST_INSERT_ID() AS sequence;
The third query is guaranteed to return a unique sequence number. This guarantee holds even if you have dozens of different client programs connected to your database. (The DELETE query merely keeps this otherwise pointless table from taking up too much space.)
The error message you received makes it clear that you can't use a session variable in a view.
https://dev.mysql.com/doc/refman/5.7/en/create-view.html says:
A view definition is subject to the following restrictions:
The SELECT statement cannot refer to system variables or user-defined variables.
You can't create a view for your query. You'll have to execute the query directly. The only other suggestion I can make is to develop a stored procedure for the query.
It sounds like you want to create a row number for a query result, not an auto-increment column to store in the table.
MySQL 8.0.2 has added the window function ROW_NUMBER(), but 8.0 is still under development as we're writing this. Perhaps in 2018 it will be finished and released as GA.

Is it faster to alter multiple columns in the same query?

Is it any faster to add or drop multiple columns in one query, rather than executing a query for each column? For example, is this:
ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;
any faster than this?
ALTER TABLE t2 DROP COLUMN c;
ALTER TABLE t2 DROP COLUMN d;
Yes, it should be faster to run a single ALTER TABLE statement than two.
In my experience (with InnoDB on 5.1 and 5.5), MySQL doesn't seem to modify the table "in place". MySQL actually creates a new table, as copy of the old table with the specified modifications.
Two separate statements would require MySQL to do that copy operation twice.
With a single statement, you give MySQL the opportunity to make all the changes with just one copy operation. (I don't know the details of the MySQL internals, but it's possible that MySQL actually does the copy two times.)
Other database engines (MyISAM et al.) may get processed differently.
I believe the InnoDB plugin and/or newer versions of InnoDB in the MySQL (>5.5) have some algorithms other than the "copy" method, at least for some changes, which allow for the table to still be available while the ALTER TABLE is running (for read queries). But I don't know all the details.
Yes, it's faster. You only have to make one call to the database API, and it only has to parse the query once.
However, for ALTER TABLE queries, performance usually isn't a concern. You shouldn't be doing this frequently, only when you redesign your schema.
But if your question were about UPDATE queries, for instance, it would probably be significant. E.g. you should do:
UPDATE table
SET col1 = foo, col2 = bar
WHERE <condition>;
rather than
UPDATE table
SET col1 = foo
WHERE <condition>;
UPDATE table
SET col2 = bar
WHERE <condition>;

SQL command to automatically create table based on data being inserted

I have to load some data into a temporary table, but the data is never uniform, the datatype and number of columns will always be different.
Is there an SQL command that will automatically create table specifications based on data that will be loaded into it?
Assuming that you're populating it from a query, you can use the syntax CREATE TABLE tablename SELECT ...; see ยง12.1.14.1. CREATE TABLE ... SELECT Syntax in the MySQL 5.6 Reference Manual.
SELECT ... INTO should do what you want.

MySQL Creating temporary table syntax error

I am getting a syntax error when I run a MySQL statement.
I know backticks can be added to the tablename to make it work but was wondering why it happens in the first place.
Create temporary table 6514202534e1b20f0d6331 (user_id INT (10)) ENGINE=HEAP;
If I put this in Mysql Query Browser it treats the table name as two seperate words - 6514202534e1 and b20f0d6331.
The table name is generated dynamically and I haven't had a problem with this before, so I was wondering why it stopped working all of a sudden.
I think this is because the server (mysql) understands it in this case as 6514202534*e^1 INT.
Using the ` character:
CREATE TEMPORARY TABLE `6514202534e1b20f0d6331` (user_id INT (10)) ENGINE=HEAP;
In this way the MySQL Server understands (explicitly) that the whole phrase is database, table or field not a value or function, etc.
For example `order` is legal while just order will rise an error for invalid order clause.