Is there a standardized way I can create a table in SQL with a column (lets call it ID) that is auto incremental so that I can basically use it in all databases?
(e.g. standardized in SQL-92)
If so - how? If not, why? I think auto_increment is a very often used property so I thought it would be very important to standardize it…
Nope, sorry. There is AUTO_INCREMENT in MySQL, but e.g. in MS SQL this is called IDENTITY and SERIAL in PGSQL. Many things are not really standardized in SQL - and most are in the schema creating area.
It's a mess, but you can use stuff like e.g. Hibernate/NHibernate to try to use a single code base.
Update: Few year later there is a more standard way that some DBMS support (e.g. PG SQL from version 10.0, so from October 2017):
GENERATED BY DEFAULT AS IDENTITY -- the value has a default auto incrementation, but you can insert your own.
GENERATED ALWAYS AS IDENTITY -- forbids inserting own values (in a standard query, might be overriden)
This is something that should work in PG SQL 10+, DB2, Oracle:
DROP TABLE IF EXISTS simple_test;
CREATE TABLE simple_test(
s_id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
);
Note however that this will not work in Microsoft SQL Server (not even in MS SQL Server 2022). MSSQL does not support the generated keyword. MySQL/MariaDb has generated columns, but MariaDb does not support the identity syntax.
So yeah, 10 years later the answer is kind of the same really -- it is still a mess and you should probably use a framework for that.
You can use so-called identity columns:
CREATE TABLE foo(id int GENERATED ALWAYS AS IDENTITY);
This is in the SQL standard and should be supported by PostgreSQL 10 and Oracle:
https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/#comment-248607
In Oracle you need to create a SEQUENCE
SQLite uses it for rowid and a synonym of it e.g. RowIdSyn INTEGER PRIMARY KEY AUTOINCREMENT
Related
I'm currently writing tests for a spring boot application which is using a postgreSQL database. During test I want to replace the database by some in-memory variant like H2 or HSQLDB. Sadly both do not behave the same as the postgreSQL database.
I have migrations that look like
CREATE TABLE foo(id BIGSERIAL PRIMARY KEY, ...)
This results in hsqldb telling me
SQL State : 42525
Error Code : -5525
Message : identity definition not allowed: FOO_ID
So apparently creating the matching sequence for the primary key is forbidden. Is there a way to tell hsqldb to accept this?
You need to set PostgreSQL compatibility mode in HSQLDB.
SET DATABASE SQL SYNTAX PGS TRUE
Your table definition is then accepted and converted internally to the SQL Standard equivalent.
CREATE TABLE FOO(ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY, ..
I'm porting a SQL Server based app to Oracle. Our Oracle DBA has given me a schema that was supposed to be identical to the original SQL Server schema (and generated from it), but the auto generated keys are missing. I am trying to alter these table PK's from a normal INT to incrementing. I am doing so with Oracle SQL Developer 4.0.3 and Oracle 12c.
The error I receive is ORA-01442: column to be modified to NOT NULL is already NOT NULL
I get this after editing the table, selecting the column and setting it's Identity dropdown to 'Generated as Identity'. I am not sure why SQl Developer is attempting to make it not null when it's already a PK.
My questions are: Is this the proper way to setup a generated key? How can I get around this? If I go alter all the required columns, can the DBA use the schema to regenerate whatever procedure he used to create it in the first place to allow proper generated keys and is there a better solution for creating a good schema to go forward with?
Thanks.
If the column is already definied as NOT NULL there is no need to re-defined it as NOT NULL. Therefore you get the error ora-01442.
The best way to obtain sequence values, such as identity in SQL Server, is define the column with default sequence, before inserting row:
CREATE SEQUENCE SEQ_NAME
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
ALTER TABLE table_name MODIFY column_name INT DEFAULT SEQ_NAME.NEXTVAL;
PD: This DEFAULT works with 12 c. To 11g or less, you must create a trigger
I need a very simple thing in SQL Database - I am using SQL Server and/or SQL Compact.
In c# I would write it like this
public class MyApp
{
public static int Version = 1;
}
e.g. I need to store configuration information in a form of singleton in SQL database.
Is there any better method than to create table with only one record?
Actually for my present needs it would be sufficient to have only one version number stored with database, but it must work both for SQL Server and SQL Compact database.
A table with one row is probably your best approach. Normally, you'd use a CHECK() constraint to guarantee you'll have only one row.
create table your_table_name (
one_row integer not null unique
default 1 check (one_row = 1),
version varchar(5) not null unique
);
insert into your_table_name values (1, '0.0.0');
If your platform doesn't support CHECK() constraints, but does support GRANT and REVOKE, you might be able to insert one row into the version table, then grant only update permissions. (Revoke delete and insert permissions.)
If your platform doesn't support CHECK() constraints, and doesn't support GRANT and REVOKE, but does support foreign key references, you might be able to replace the CHECK() constraint above with a foreign key reference to single-row table. This doesn't entirely solve the problem--you still have a single-row table that you can't adequately constrain.
If your dbms supports regular expressions in CHECK() constraints, you could add additional constraints to guarantee your version number follows a regular expression. You could also split the "version" into several columns of integers, each with its own constraints. But varchar(5) and varchar(7) seem to be the most common.
I want to create a table for making a comment box. I was told that I should be wary of sql injection (dont even know what that means).
So I thought I should ask around at SO. my requirements are:
Comments table
a comment row ~400 chars
aid -> every comment should be linked to an aid. duplicates should be allowed. means aid = 21, can have more than 1 comment. I should be able to search through the DB to see all the comments related to aid = 21.
timestamp for the comment
userid for the comment.
A MySQL query for the above table that should not allow SQL injection. I am pretty confused. any help would be highly appreciated. thanks a lot in advance.
Creating a table usually happens only once, when the system is installed. There is, therefore, no risk of SQL injection (which happens when a query is run with data provided by the user).
The above description would probably be implemented as:
CREATE TABLE `comment` (
`comment_id` INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
`comment_text` VARCHAR(400) NOT NULL,
`aid_id` INTEGER NOT NULL REFERENCES `aid`(`aid_id`),
`comment_time` DATETIME NOT NULL,
`user_id` INTEGER NOT NULL REFERENCES `user`(`user_id`)
);
Try and use stored procedures in mysql .
Use parameters to pass the input to the stored procedure.
thuis tutorial is for you .
http://www.tizag.com/mysqlTutorial/mysql-php-sql-injection.php
SQL injection is explained at Wikipedia and other places.
Use mysql_real_escape_string() or stored procedures are standard techniques that will avoid SQL injection.
Is it possible to change the default collation based on a column? i want to make 1 column case sensitive but all the others not
ALTER TABLE ALTER COLUMN allows to change collation for a single column:
alter table Foo alter column Bar ntext collate Latin1_General_CS_AS
(collation might be incorrect)
I don't specifically know SQL Server, but the generally accepted DBMS practice (for compatibility) would be to either:
put insert and update triggers on the table so that they're stored in the case you want.
use generated columns to store another copy of the column in the case you want.
There may be a faster way to do it in SQL Server but you should be careful of solutions that push workload into the SELECT statements - they never scale well. It's almost always better doing this as part of inserts and updates since that's the only time data changes - doing it that way minimizes the extra workload.
The answer to your question is yes, already stated above by Anton Gogolev.
Additional Info:
Here is a how you can find list of Collation supported by your SQL Server based on its version.
select name,
COLLATIONPROPERTY(name, 'CodePage') as Code_Page,
description
from sys.fn_HelpCollations()
what is the meaning of Kanatype Sensitive KS and width sensitive