How can I create a table that only allows data to insert if they are allowed - sql

How can i create a table, that allows only to put data in NAME, if the data matches with the data that i want to be allowed in NAME. So like Bla1 or Bla2.
CREATE TABLE Table1 (
NAME VARCHAR(23)
NAME has to be one of them: ('Bla1', 'Bla2')
)

The best way to do it is probably to have a second table with all the allowed names in it, and making a FOREIGN KEY from the name field in your Table1 to the name field in that other table. That'll automatically fail any insert queries for which the name is not contained in the list of allowed names.
This has an advantage over things like ENUM and such in that it does not require you to rebuild your table (which is a very expensive operation) every time you want to allow another name and it also allows you to later add additional related info to each name by adding it to the other table.
Here's a great article on why using a foreign key is much better than using enums or other such checks in the table itself: http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

Try this:
CREATE TABLE Table1 (
name VARCHAR(23) CHECK( name IN ('Bla1','Bla2') )
);

Related

How to create a primary key column and fill it with integer values on HANA SQL

I searched but only could found partial answer to this question
The goal would be here to create a new ID column on an existing table.
This new column would be the primary key for the table and I simply want it to be filled with integer values from 1 to number of rows.
What would be the query for that?
I know I have to first alter table to create the new column :
ALTER TABLE <MYTABLE> ADD (ID INTEGER);
Then I could use the series generator :
INSERT INTO <MYTABLE.ID> SELECT SERIES_GENERATE_INTEGER(1,1,(number of rows));
Once the column is filled I could use this line:
ALTER TABLE <MYTABLE> ADD PRIMARY KEY ("ID");
I am sure there is an easier way to do this
You wrote that you want to add a "new ID column to an existing table" and fill it with unique values.
That's not a "standard" operation in any DBMS, as the usual assumption is that records are created with a primary key and not retro fitted.
Thus, "ease" of operation for this is relative to what else you want to do.
For example, if you want to continue using this ID as a primary key for further operations, then using a once-off generator function like the SERIES_GENERATE_INTEGER or a query won't be very helpful since you have to avoid duplicates of already existing values.
Two, relatively easy, options come to mind:
Using a sequence:
create sequence myid;
update <table> set ID = myid.nextval;
And for succeeding inserts:
insert into <table> (id, ..., ...) VALUES (myid.nextval, ..., ...) ;
Note that this generates a value for every existing record and not a predefined set of size X.
Using a GUID
By using a GUID you generate a unique value every time you call the 'SYSUUID' function in SAP HANA. check docu here
Something like
update <table> set ID = SYSUUID;
should do the trick here.
Subsequent inserts would simply call the function for values of ID.

Oracle: selfcopying data from Oracle tables

Application has different versions. Each version has it's own set of values in each table. I need to provide functionality to copy data from one version to another. Problem :
By inserting data I am trying to insert Ids which has already been in use in this table. So, I need to change ids of components which I want to insert but I must save relationship between those components. How cat I do that?
Create a master table which has a surrogate key as your primary key. A numeric value of type NUMBER(9) works well. You can create a sequence and trigger to automatically insert this.
The rest of the table is the column of your current table plus a column to indicate which version the row is for.
For simplicity you may wish to create views on top of the table along the lines of
select * from master_table where version_id = ####;
To copy the data from one version to another this will work:
Insert into master_table seq_master_table.nextval, new version_id,.....
from master_table
where version_id = ####;

Can a table and a column within it use the same name in Sybase?

I am using a Sybase database and would like to know if it's valid to have a table contain a column with the same name as that of the table, e.g.:
CREATE TABLE foo
(
foo int not null,
etc...
)
Valid? Sure. Recommended? No.
Yes, we can surely do that but as said it is not recommended. But why are we able to do so? Well, because a table name entry goes into the system table sysobjects however column entries go in the system table syscolumns.
Therefore there is no restriction in using table name as column name, however using table name as column name usually is not recommended because it makes your table structure a bit confusing and also it adds bad practice to database design.

increase Ids in table

I would like to increase all ids in my table by 1000 cause I need to insert there data from other table with excactly the same ids. What is the best way to do that?
update dbo.table set id = id + 1000
go
The best way to go is to not do that. You have to change all related records as well and if you are using identities it gets even more complicated. If you do anything wrong you will seriousl mess up your data integrity. I would suggest that the data you want to insert is the data that needs to have the values changed and if you need to relate back to the data in another tbale, store the original ID in a new field in the table called something like table2id or database2id. If you can't change the existing table, then you can use a lookup table that has both the old id value and the new one.
Under no circumstances should you attempt something of this nature without taking a backup first.
First as HLGEM it seems to be a bad id (think about your foreign keys on id's you must add 1000 to them to).
Second dbo.table has become sys.tables in Server 2008.
Finally you'll need to find the foreign keys columns with this request :
SELECT name,OBJECT_NAME(object_id)
FROM sys.columns
WHERE name like '%id' or name like 'id%'
--depends on where is 'id' in your columns names
name : the column name, OBJECT_NAME : the table name
And update the whole thing (with a tricky request that should looks like this one, but i didn't test with the "update" command) :
CREATE TABLE #TablesWithIds (
columnName varchar(100),
tableName varchar(100)
)
Insert into #TablesWithIds
SELECT name as columnName,OBJECT_NAME(object_id) as tableName
FROM sys.columns
WHERE name like '%id%'
update #TablesWithIds.tableName set #TablesWithIds.columnName = #TablesWithIds.columnName +1000
drop table #TablesWithIds

SQL: dealing with unique values in the table when UNIQUE key constraint isn't applicable

What you do when you need to maintain a table with unique values when you can't use UNIQUE constraint?
For example, I use MySQL and want to map my urls to ids. So I create a table:
CREATE TABLE url (id INTEGER PRIMARY KEY AUTO_INCREMENT, url VARCHAR(2048));
The problem is that mysql doesn't allow unique field bigger than 1000 bytes.
How in general do insert only if not exist in sql atomically?
You could create an extra field which would be the hash of a url e.g. md5, and make that hash field unique. You can certainly be sure that the URL is unique then, and with almost 100% certainty you can insert a new URL if it isn't already there.
It is tempting to create a table lock, however creating a table lock will implicitly commit the transaction you are working on: http://www.databasesandlife.com/mysql-lock-tables-does-an-implicit-commit/
You could create a single-row table e.g. name mutex, type=InnoDB, insert a row into it, and do a select for update on that row to create a lock which is compatible with transactions. It's nasty but that's the way I do table locks in MySQL in my applications :(
You could use a not exist condition:
insert YourTable
(url)
values ('blah blah blah')
where not exists
(
select *
from YourTable
where url = 'blah blah blah'
)
In my opinion the best way to handle it is to write a trigger. The trigger is going to check each value in the table to see whether they are equal and if yes, to raise an error. However, I don't think an URL will go beyond 1000 characters but if it does in your case, you should write a trigger to handle the uniqueness.