NVARCHAR with variable length? - sql

I want to create a table in SQL which has a string attr for Users of a website. How should I declare this attr, since names don't have a max length? Can I just leave the length empty and do it like this?
CREATE TABLE User(
id NUMBER PRIMARY KEY NOT NULL
name NVARCHAR
)
Also, do I need to say NOT NULL for PRIMARY KEYS, or are primary keys already never null?
Thanks in advance :)

You should declare length as MAX and primary key are automatically NOT NULL
CREATE TABLE User(
id NUMBER PRIMARY KEY
name NVARCHAR(MAX)
)
Since you have later specified dbms as SQL Lite , the documentation says
What is the maximum size of a VARCHAR in SQLite?
SQLite does not enforce the length of a VARCHAR. You can declare a
VARCHAR(10) and SQLite will be happy to let you put 500 characters in
it. And it will keep all 500 characters intact - it never truncates.

How should I declare this attr, since names don't have a max length?
Can I just leave the length empty and do it like this?
Yes, in SQLite you can just declare the column with any “text affinity” type name (CHAR, TEXT, CLOB, etc.) and it will store strings (or blobs) without length restriction (except for the global string length limit, which is 1 GB by default).
If you do want to constrain the length of strings, you can do it with an explicit CHECK constraint, like CHECK(LENGTH(name) <= 100).
Also, do I need to say NOT NULL for PRIMARY KEYS, or are primary keys
already never null?
Per the SQL standard, PRIMARY KEY implies NOT NULL. However, SQLite has a long-standing bug that makes the explicit NOT NULL constraint required.
According to the SQL standard, PRIMARY KEY should always imply NOT NULL. Unfortunately, due to a bug in some early versions, this is not
the case in SQLite. Unless the column is an INTEGER PRIMARY KEY or the
table is a WITHOUT ROWID table or the column is declared NOT NULL,
SQLite allows NULL values in a PRIMARY KEY column. SQLite could be
fixed to conform to the standard, but doing so might break legacy
applications. Hence, it has been decided to merely document the fact
that SQLite allowing NULLs in most PRIMARY KEY columns.

Related

Postgresql change column type from UUID to int4

I wanted to change dataType of column from UUID to int4
ALTER TABLE tableA ALTER COLUMN columnA TYPE int4(32);
But it is giving me an error.
ERROR: type modifier is not allowed for type "int4"
I tried to search on internet and found that I have to use USING but don't know how to use it.
You cannot really turn a UID into an int. There are just too many values, so you run the risk of collisions (which rises to 100% as the table gets bigger).
My guess is that you really want an id column on the table. If so, add a new column and remove the old one:
alter table tableA add a_id int generated always as identity,
drop columnA;
Note: in older versions of Postgres, you would use serial instead of int generated always as identity.
Your 32 is syntactically treated as a modifier. Modifiers are allowed for numeric and decimal types, but not for plain ints, int4(xxx) is not a valid type in Postgres (I believe it is in mysql) int4 is just an alias for integer.

Date sqlite3 in a CREATE TABLE

I am following a tutorial and encountered the following code. What does date mean here? I thought date was not supported in sqlite3.
create table log_date (
id integer primary key autoincrement,
entry_date date not null
);
SQLite does not have a DATE type, but that doesn't mean it won't let you use it in a CREATE TABLE and then use a different data type underneath.
DATE is converted to NUMERIC as described in Affinity Name Examples.
There's a prioritized set of rules to determine what a not-formally-supported type gets converted to, and DATE/DATETIME both work out to NUMERIC.
date is the type affinity, which due to SQLite's flexibility is actually a type affinity of NUMERIC (see 3.1 in the link below for how the type affinity is determined).
The type affinity specified can be virtually anything (not KEYWORDS and there are limitations in regards to values in parenthesises). A type affinity of grUmpleStiltskin is even usable (again gets converted to the NUMERIC bucket).
However, due to SQLite's flexibility any type of data can be stored in any type of column (with the exception of a column that is an alias of the rowid (as is your id column as it has INTEGER PRIMARY KEY), an alias of the rowid column, or the rowid column itself can only store an Integer value (64 bit signed)).
You may wish to have a read of Datatypes In SQLite Version 3.
one called ID that has to be an integer, it is assigned a unique key
and updates (w.e that means).
As said because you have INTEGER PRIMARY KEY then the id column is an alias of the normally hidden rowid column. If no value is specified when inserting a row then SQLite will attempt to assign a unique 64 bit integer value. It will typically be 1 greater than the highest existing rowid.
AUTOINCREMENT, as you have coded, introduces a rule/constraint that only values higher than the highest used (even if deleted) rowid value. AUTOINCREMENT can only be used for columns that are aliases of the rowid column can be used.
However, the very first sentence in SQLite Autoincrement is :-
The AUTOINCREMENT keyword imposes extra CPU, memory, disk space, and
disk I/O overhead and should be avoided if not strictly needed. It is
usually not needed.

HSQLDB UNIQUE constraint and SQL Array Type

I am developing with HSQLDB 2.2.9. HSQLDB is one of the RDBMS's out there that supports the SQL Array type and I want to use this capability to address some functionality in my database.
I've been running some command line queries as I develop my database, but I am not sure how the UNIQUE constraint is handled by HSQLDB when declared for a column of type VARCHAR(24) ARRAY[]. The DDL I am using follows:
CREATE CACHED TABLE Clients (
cli_id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
mrn VARCHAR(24) ARRAY DEFAULT ARRAY[] NOT NULL UNIQUE,
lastname VARCHAR(48) NOT NULL,
firstname VARCHAR(24) NOT NULL,
dob INTEGER DEFAULT 0 NOT NULL
);
The mrn column contains an identifier that is unique for each client. As I've developed this database, I've learned that a client may have one or more than one mrn's. One solution to this problem is to use the mrn column to store an array of mrn's for each client.
What are the semantics of UNIQUE in this circumstance? Does HSQLDB assert that each element in the array satisfies the UNIQUE column constraint?
This answer Can PostgreSQL have a uniqueness constraint on array elements? suggests that Postgres 9.1 is unable to enforce the UNIQUE column constraint on SQL Array type elements. I wonder if this may be the case for HSQLDB as well.
HSQLDB supports UNIQUE constraints on arrays. A Unique constraint on an array column results in comparison of the whole array stored in different rows to ensure they are distinct.
Two arrays are considered equal when they have equal elements at each index and the lengths of the arrays are the same.
For your application, you must ensure the array does not contain nulls and its elements are sorted.

which constraint makes sure a column has some value entered?

which constraint makes sure a column has some value entered? I am confused between primary key and not null constraint .
A NOT NULL constraint.
All columns that participate in a PK must also not allow NULL but the PK constraint guarantees something more, uniqueness, - i.e. no two rows in the table can have the same value for the primary key.
In SQL Server even though syntactically you can name a NOT NULL constraint in the DDL it is different from other constraints in that no metadata (including even the name) is actually stored for the constraint itself.
CREATE TABLE T
(
X INT CONSTRAINT NotNull NOT NULL
)
Another point I didn't see addressed: NULL and empty string are two very different things, but they are often deemed interchangeable by a large portion of the community.
You can declare a varchar column as NOT NULL but you can still do this:
DECLARE #x TABLE(y VARCHAR(32) NOT NULL);
INSERT #x(y) VALUES('');
So if your goal is to make sure there is a valid value that is neither NULL nor a zero-length string, you can also add a check constraint, e.g.
DECLARE #x TABLE(y VARCHAR(32) NOT NULL CHECK (DATALENGTH(LTRIM(y)) > 0));
NOT NULL
is the condition that a field has a value. You can enforce that a field always have a value entered for every record inserted or updated, making the field NOT NULL in the table definition.
A primary key must meet these three conditions:
The values of the field are NOT NULL.
The values are unique.
The values are immutable.
The database can enforce the first two conditions with a unique index (and a not null condition on the field).
The third condition is not typically enforced by the database. Databases will typically allow changes to primary key fields, so DBAs can "fix" them. So the third condition is more philosophical, in that you agree to use the key for identification, and not write an application which changes the value, unless intended for an administrator to fix the keys.
I have been using field here, but a primary key can be a compound primary key, made up of any combination of fields which meets the conditions. Any combination of fields which matches the first 2 or all 3 conditions is called a candidate key.
Only one candidate key can be used as the primary key. Which one is just an arbitrary choice.

VARCHAR as foreign key/primary key in database good or bad?

Is it better if I use ID nr:s instead of VARCHARS as foreign keys?
And is it better to use ID nr:s isntead of VARCHARS as Primary Keys?
By ID nr I mean INT!
This is what I have now:
category table:
cat_id ( INT ) (PK)
cat_name (VARCHAR)
category options table:
option_id ( INT ) (PK)
car_id ( INT ) (FK)
option_name ( VARCHAR )
I COULD HAVE THIS I THINK:
category table:
cat_name (VARCHAR) (PK)
category options table:
cat_name ( VARCHAR ) (FK)
option_name ( VARCHAR ) ( PK )
Or am I thinking completely wrong here?
The problem with VARCHAR being used for any KEY is that they can hold WHITE SPACE. White space consists of ANY non-screen-readable character, like spaces tabs, carriage returns etc. Using a VARCHAR as a key can make your life difficult when you start to hunt down why tables aren't returning records with extra spaces at the end of their keys.
Sure, you CAN use VARCHAR, but you do have to be very careful with the input and output. They also take up more space and are likely slower when doing a Queries.
Integer types have a small list of 10 characters that are valid, 0,1,2,3,4,5,6,7,8,9. They are a much better solution to use as keys.
You could always use an integer-based key and use VARCHAR as a UNIQUE value if you wanted to have the advantages of faster lookups.
My 2 cents:
From a performance perspective, using CHAR or VARCHAR as primary key or index is a nightmare.
I've tested compound primary keys (INT + CHAR, INT + VARCHAR, INT + INT) and by far INT + INT was the best performance (loading a data warehouse). Lets say about twice more performance if you keep only numeric primary keys/indexes.
When I'm doing design work I ask myself: have I got anything in this data that I can guarantee is going to be non-NULL, unique, and unchanging? If so that's a candidate to be the primary key. If not, I know I have to generate a key value to use. Assuming, then, that my candidate key happens to be a VARCHAR I then look at the data. Is it reasonably short in length (meaning, say, 20 characters or less)? Or is the VARCHAR field rather long? If it's short it's usable as a key - if it's long, perhaps it's better to not use it as a key (although if it's in consideration for being the primary key I'm probably going to have to index it anyways). At least part of my concern is that the primary key is going to have to be indexed and will perhaps be used as a foreign key from some other table. Comparisons of VARCHAR fields tend to be slower than the comparison of numeric fields (particularly binary numeric fields such as integers) so using a long VARCHAR field as a key may result in slow performance. YMMV.
with an int you can store up to 2 billion in 4 bytes with varchars you cannot you need to have 10 bytes or so to store that, if you use varchars there is also a 2 byte overhead
so now you add up the 6 extra bytes in every PK and FK + the 2 byte varchar overhead
I would say it is fine to use VARCHAR as both PRIMARY and FOREIGN KEYS.
Only issue I could forsee is if you have a table, lets say Instruments (share instruments) and you create the PRIMARY/FOREIGN KEY as VARCHAR, and it happens that the CODE changes.
This does happen on Stock Exchanges, and would require you to rename all references to this CODE, where as a ID nr would not require this from you.
So to conclude, I would say this dependes on your intended use.
EDIT
When I say CODE, I mean the Ticker Code for lets say GOOG, or any other share. It is possible for these codes to change over time, lets say you look at Dirivative/Future instruments.
If you make the category name into the ID you will have a problem if you ever decide to rename a category.
There's nothing wrong with either approach, although this question might start the usual argument of which is better: natural or surrogate keys.
If you use CHAR or VARCHAR as a primary key you'll end up using it as a forign key at some point. When it comes down to it, as #astander says, it depends on your data and how you are going to use it.