How can I set a size limit for an "int" datatype in PostgreSQL 9.5 - sql

I am experimenting with PostgreSQL coming from SQL using MySQL and I simply wish to create a table with this piece of code which is valid SQL:
CREATE TABLE flat_10
(
pk_flat_id INT(30) DEFAULT 1,
rooms INT(10) UNSIGNED NOT NULL,
room_label CHAR(1) NOT NULL,
PRIMARY KEY (flat_id)
);
I get the error
ERROR: syntax error at or near "("
LINE 3: pk_flat_id integer(30) DEFAULT 1,
I have conducted searches on the web and found no answer and I cant seem to find an answer in the PostgreSQL manual. What am I doing wrong?
I explicitly want to set a limit to the number of digits that can be inserted into the "pk_flat_id" field

I explicitly want to set a limit to the number of digits that can be inserted into the "pk_flat_id" field
Your current table definition does not impose a "size limit" in any way. In MySQL the parameter for the intdata type is only a hint for applications on the display width of the column when displaying it.
You can store the value 2147483647 in an int(1) without any problems.
If you want to limit the values to be stored in an integer column you can use a check constraint:
CREATE TABLE flat_10
(
pk_flat_id bigint DEFAULT 1,
rooms integer NOT NULL,
room_label CHAR(1) NOT NULL,
PRIMARY KEY (flat_id),
constraint valid_number
check (pk_flat_id <= 999999999)
);

The answer is that you use numeric or decimal types. These are documented here.
Note that these types can take an optional precision argument, but you don't want that. So:
CREATE TABLE flat_10
(
pk_flat_id DECIMAL(30) DEFAULT 1,
rooms DECIMAL(10) NOT NULL,
room_label CHAR(1) NOT NULL,
PRIMARY KEY (pk_flat_id)
);
Here is a SQL Fiddle.
I don't think that Postgres supports unsigned decimals. And, it seems like you really want serial types for your keys and the long number of digits is superfluous.

Changing integer to numeric works.
CREATE TABLE flat_10
(
pk_flat_id bigint DEFAULT 1,
rooms numeric NOT NULL,
room_label CHAR(1) NOT NULL,
);

Related

How to prevent a input of certain letters using Oracle

The code is the category of the video, it is represented by one upper case character, excluding I, O,
Q, V, Y and Z, followed by a numeric character.
So far, I took a guess and got this. Any suggestions on how to fix it?
create table channelTable (
channelID number NOT NULL,
ChannelName varchar(100) NOT NULL,
ChannelDate date NOT NULL,
UserName varchar(100) NOT NULL UNIQUE,
TopicCode varchar(4) NOT NULL);
CONSTRAINT channelID_pk PRIMARY KEY (channelID)
CONSTRAINT c_topicCode LIKE '[A-Za-z][0-9] NOT (I,O,Q,N,Y,Z)
);
Some comments:
NOT NULL is not needed for PRIMARY KEY columns.
In Oracle, use VARCHAR2().
Then, I would suggests regular expressions. If the value is supposed to be exactly two characters, then declare it as such:
create table channelTable (
channelID number,
ChannelName varchar(100) NOT NULL,
ChannelDate date NOT NULL,
UserName varchar2(100) NOT NULL UNIQUE,
TopicCode char(2) NOT NULL;
CONSTRAINT channelID_pk PRIMARY KEY (channelID)
CONSTRAINT check (REGEXP_LIKE(c_topicCode, '^[A-HJ-NPR-UYZ][0-9]$')
);
Or perhaps more simply:
CONSTRAINT REGEXP_LIKE(c_topicCode, '^[A-Z][0-9]$') AND NOT REGEXP_LIKE(c_topicCode, '^[IOQNYZ]'))
All that said, I would rather see a table of TopicCodes that is populated with the correct values. Then you can just use a foreign key relationship to define the appropriate codes.
Use the regular expression ^[A-HJ-MPR-X]\d$ to match an upper-case character excluding I,O,Q,N,Y,Z followed by a digit:
CREATE TABLE channels (
id number CONSTRAINT channel__id__pk PRIMARY KEY,
Name varchar(100) CONSTRAINT channel__name__nn NOT NULL,
DateTime date CONSTRAINT channel__date__nn NOT NULL,
UserName varchar(100) CONSTRAINT channel__username__NN NOT NULL
CONSTRAINT channel__username__U UNIQUE,
TopicCode varchar(4),
CONSTRAINT channel__topiccode__chk CHECK ( REGEXP_LIKE( topiccode, '^[A-HJ-MPR-X]\d$' ) )
);
db<>fiddle
Also, you don't need to call the table channeltable just call it channels and you don't need to prefix the column names with the table name and you can name all the constraints (rather than relying on system generated constraint names which makes it much harder to track down issues when you are debugging).
Consider the following check constrait:
create table channelTable (
...
topicCode varchar(4) not null
check(
substr(c_topicCode, 1, 1) not in ('I', 'O', 'Q', 'V', 'Y', 'Z')
and regexp_like(topicCode, '^[A-Z]\d')
),
...
);
The first condition ensures that the code does not start with one of the forbidden characters, the second valides that it stats with an upper alphabetic character, followed by a number.
To avoid using two conditions, an alternative would be to list all allowed characters in the first position:
check(regexp_like(topicCode, '^[ABCDEFGHJKLMNPRSTUVWX]\d'))
This works in Oracle, and in very recent versions of MySQL.

Why does Diesel fail to migrate a PostgresSQL database when the columns specify a length? [duplicate]

I am experimenting with PostgreSQL coming from SQL using MySQL and I simply wish to create a table with this piece of code which is valid SQL:
CREATE TABLE flat_10
(
pk_flat_id INT(30) DEFAULT 1,
rooms INT(10) UNSIGNED NOT NULL,
room_label CHAR(1) NOT NULL,
PRIMARY KEY (flat_id)
);
I get the error
ERROR: syntax error at or near "("
LINE 3: pk_flat_id integer(30) DEFAULT 1,
I have conducted searches on the web and found no answer and I cant seem to find an answer in the PostgreSQL manual. What am I doing wrong?
I explicitly want to set a limit to the number of digits that can be inserted into the "pk_flat_id" field
I explicitly want to set a limit to the number of digits that can be inserted into the "pk_flat_id" field
Your current table definition does not impose a "size limit" in any way. In MySQL the parameter for the intdata type is only a hint for applications on the display width of the column when displaying it.
You can store the value 2147483647 in an int(1) without any problems.
If you want to limit the values to be stored in an integer column you can use a check constraint:
CREATE TABLE flat_10
(
pk_flat_id bigint DEFAULT 1,
rooms integer NOT NULL,
room_label CHAR(1) NOT NULL,
PRIMARY KEY (flat_id),
constraint valid_number
check (pk_flat_id <= 999999999)
);
The answer is that you use numeric or decimal types. These are documented here.
Note that these types can take an optional precision argument, but you don't want that. So:
CREATE TABLE flat_10
(
pk_flat_id DECIMAL(30) DEFAULT 1,
rooms DECIMAL(10) NOT NULL,
room_label CHAR(1) NOT NULL,
PRIMARY KEY (pk_flat_id)
);
Here is a SQL Fiddle.
I don't think that Postgres supports unsigned decimals. And, it seems like you really want serial types for your keys and the long number of digits is superfluous.
Changing integer to numeric works.
CREATE TABLE flat_10
(
pk_flat_id bigint DEFAULT 1,
rooms numeric NOT NULL,
room_label CHAR(1) NOT NULL,
);

Create named Column default in CREATE TABLE statement in ANSI SQL

I want to create a named default value in an ANSI compliant fashion, if possible, in a CREATE TABLE statement
If I try to add the CONSTRAINT as I would normally write it in an ALTER TABLE statement, it fails (at least in SQL SERVER, though I emphasise I am hoping to find an ANSI complaint statement as I would prefer it to work over a variety of Ado.NET DbConnections).
Example:
CREATE TABLE [dbo].[MyExample]
(
Id int NOT NULL IDENTITY (1, 1),
Name varchar(512) NOT NULL,
IsActive bit NOT NULL,
CONSTRAINT PK_MyExample PRIMARY KEY CLUSTERED (Id),
CONSTRAINT DF_MyExample_IsActive DEFAULT (1) FOR [IsActive]
)
Error:
Incorrect syntax near 'for'.
In terms of the SQL-92 Standard -- which is both ISO (I = International) and ANSI (A + American), by the way -- DEFAULT is not a constraint that may be given a name. In SQL-92 the DEFAULT can only be defined inline with the column definition and must be between the data type and the NOT NULL (if used) e.g.
CREATE TABLE T (c INTEGER DEFAULT 1 NOT NULL UNIQUE);
Note you have much non-Standard syntax in your small example:
square brackets as quoted identifiers (should be double quotes)
non-compliant data type (e.g. incorrect bit null behaviour)
abbreviated data types (e.g. int rather than INTEGER)
IDENTITY
CLUSTERED
Is it not ANSI compliant?
CREATE TABLE [dbo].[MyExample]
(
Id int NOT NULL IDENTITY (1, 1),
Name varchar(512) NOT NULL,
IsActive bit NOT NULL CONSTRAINT DF_MyExample_IsActive DEFAULT (1),
CONSTRAINT PK_MyExample PRIMARY KEY CLUSTERED (Id)
)

Ensuring uniqueness of multiple large URL fields in MS SQL

I have a table with the following definition:
CREATE TABLE url_tracker (
id int not null identity(1, 1),
active bit not null,
install_date int not null,
partner_url nvarchar(512) not null,
local_url nvarchar(512) not null,
public_url nvarchar(512) not null,
primary key(id)
);
And I have a requirement that these three URLs always be unique - any individual URL can appear many times, but the combination of the three must be unique (for a given day).
Initially I thought I could do this:
CREATE UNIQUE INDEX uniques ON url_tracker
(install_date, partner_url, local_url, public_url);
However this gives me back the warning:
Warning! The maximum key length is 900 bytes. The index 'uniques' has maximum
length of 3076 bytes. For some combination of large values, the insert/update
operation will fail.
Digging around I learned about the INCLUDE argument to CREATE INDEX, but according to this question converting the command to use INCLUDE will not enforce uniqueness on the URLs.
CREATE UNIQUE INDEX uniques ON url_tracker (install_date)
INCLUDE (partner_url, local_url, public_url);
How can I enforce uniqueness on several relatively large nvarchar fields?
Resolution
So from the comments and answers and more research I'm concluding I can do this:
CREATE TABLE url_tracker (
id int not null identity(1, 1),
active bit not null,
install_date int not null,
partner_url nvarchar(512) not null,
local_url nvarchar(512) not null,
public_url nvarchar(512) not null,
uniquehash AS HashBytes('SHA1',partner_url+local_url+public_url) PERSISTED,
primary key(id)
);
CREATE UNIQUE INDEX uniques ON url_tracker (install_date,uniquehash);
Thoughts?
I would make a computed column with the hash of the URLs, then make a unique index/constraint on that. Consider making the hash a persisted computed column. It shouldn't have to be recalculated after insertion.
Following the ideas from the conversation in the comments. Assuming that you can change the datatype of the URL to be VARCHAR(900) (or NVARCHAR(450) if you really think you need Unicode URLs) and be happy with the limitation on the length of the URL, this solution could work. This also assumes SQL Server 2008 or better. Please, always specify what version you're working with; sql-server is not specific enough, since solutions can vary greatly depending on the version.
Setup:
USE tempdb;
GO
CREATE TABLE dbo.urls
(
id INT IDENTITY(1,1) PRIMARY KEY,
url VARCHAR(900) NOT NULL UNIQUE
);
CREATE TABLE dbo.url_tracker
(
id INT IDENTITY(1,1) PRIMARY KEY,
active BIT NOT NULL DEFAULT 1,
install_date DATE NOT NULL DEFAULT CURRENT_TIMESTAMP,
partner_url_id INT NOT NULL REFERENCES dbo.urls(id),
local_url_id INT NOT NULL REFERENCES dbo.urls(id),
public_url_id INT NOT NULL REFERENCES dbo.urls(id),
CONSTRAINT unique_urls UNIQUE
(
install_date,partner_url_id, local_url_id, public_url_id
)
);
Insert some URLs:
INSERT dbo.urls(url) VALUES
('http://msn.com/'),
('http://aol.com/'),
('http://yahoo.com/'),
('http://google.com/'),
('http://gmail.com/'),
('http://stackoverflow.com/');
Now let's insert some data:
-- succeeds:
INSERT dbo.url_tracker(partner_url_id, local_url_id, public_url_id)
VALUES (1,2,3), (2,3,4), (3,4,5), (4,5,6);
-- fails:
INSERT dbo.url_tracker(partner_url_id, local_url_id, public_url_id)
VALUES(1,2,3);
GO
/*
Msg 2627, Level 14, State 1, Line 3
Violation of UNIQUE KEY constraint 'unique_urls'. Cannot insert duplicate key
in object 'dbo.url_tracker'. The duplicate key value is (2011-09-15, 1, 2, 3).
The statement has been terminated.
*/
-- succeeds, since it's for a different day:
INSERT dbo.url_tracker(install_date, partner_url_id, local_url_id, public_url_id)
VALUES('2011-09-01',1,2,3);
Cleanup:
DROP TABLE dbo.url_tracker, dbo.urls;
Now, if 900 bytes is not enough, you could change the URL table slightly:
CREATE TABLE dbo.urls
(
id INT IDENTITY(1,1) PRIMARY KEY,
url VARCHAR(2048) NOT NULL,
url_hash AS CONVERT(VARBINARY(32), HASHBYTES('SHA1', url)) PERSISTED,
CONSTRAINT unique_url UNIQUE(url_hash)
);
The rest doesn't have to change. And if you try to insert the same URL twice, you get a similar violation, e.g.
INSERT dbo.urls(url) SELECT 'http://www.google.com/';
GO
INSERT dbo.urls(url) SELECT 'http://www.google.com/';
GO
/*
Msg 2627, Level 14, State 1, Line 1
Violation of UNIQUE KEY constraint 'unique_url'. Cannot insert duplicate key
in object 'dbo.urls'. The duplicate key value is
(0xd111175e022c19f447895ad6b72ff259552d1b38).
The statement has been terminated.
*/

Why does this MySQL Create Table statement fail?

Using mySQLAdmin tool, I try to create a table. The tool generates the SQL statement, and then replorts a "Can't create table" with no other clue on what error it is!
Here it is :
CREATE TABLE `C121535_vubridge`.`Products` (
`pr_ID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`pr_Name` VARCHAR(45) NOT NULL,
`pr_Type` VARCHAR(2) NOT NULL COMMENT 'H=Hand Series V=VuBridge software E=Event Subs S=Sponsoring',
`pr_AuthorID` INTEGER UNSIGNED COMMENT '= m_ID (for Bridge Hand Series',
`pr_SponsorID` INTEGER UNSIGNED NOT NULL,
`pr_DateCreation` DATETIME NOT NULL,
`pr_Price` FLOAT NOT NULL,
`pr_DescriptionText` TEXT,
`pr_Description` VARCHAR(245),
PRIMARY KEY (`pr_ID`),
CONSTRAINT `FK_prAuthor` FOREIGN KEY `FK_prAuthor` (`pr_AuthorID`)
REFERENCES `Members` (`m_ID`)
ON DELETE SET NULL
ON UPDATE NO ACTION,
CONSTRAINT `FK_Sponsor` FOREIGN KEY `FK_Sponsor` (`pr_SponsorID`)
REFERENCES `Members` (`m_ID`)
ON DELETE SET NULL
ON UPDATE NO ACTION
) ENGINE = InnoDB;
Can someone help?
The CREATE TABLE works for me if I omit the foreign key references:
CREATE TABLE `Products` (
`pr_ID` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`pr_Name` VARCHAR(45) NOT NULL,
`pr_Type` VARCHAR(2) NOT NULL COMMENT 'H=Hand Series V=VuBridge software E=Event Subs S=Sponsoring',
`pr_AuthorID` INTEGER UNSIGNED COMMENT '= m_ID (for Bridge Hand Series',
`pr_SponsorID` INTEGER UNSIGNED NOT NULL,
`pr_DateCreation` DATETIME NOT NULL,
`pr_Price` FLOAT NOT NULL,
`pr_DescriptionText` TEXT,
`pr_Description` VARCHAR(245),
PRIMARY KEY (`pr_ID`)
)
...so I'm inclined to believe that C121535_vubridge.MEMBERS does not already exist. C121535_vubridge.MEMBERS needs to be created before the CREATE TABLE statement for the PRODUCTS table is run.
Just split up the create table and try one part at the time. This way you should be able to identify a single line that it fails on.
I do note in the reference manual that if a symbol subclause is given for the CONSTRAINT clause (in your case, the back-quoted strings before FOREIGN KEY in each clause, FK_prAuthor and FK_Sponsor) have to be unique over the database. Are they? If not, that symbol can be omitted and InnoDB will assign then automatically.
Similarly, the tables your FKs refer to may not have the structure that this create statement expects.