I wrote a simple insert into statement:
insert into Worker(WorkingPlace)
select WorkingPlace
from source.Worker;
I got this error:
Cannot insert the value NULL into column 'Worker_ID', table 'Worker'; column does not allow nulls. INSERT fails
(By the way Worker.WorkingPlace is a nullable column)
I'm very confused, because I'm just inserting data into the 'WorkingPlace' column, aren't I?
insert into Worker(WorkingPlace)
select WorkingPlace
from source.Worker;
This will create as many new rows in table Worker as there are rows returned from the select.
So if your query returns 10 rows, then 10 new rows will be inserted into table Worker
This means that any column in that table that is defined as not null must receive a value, either from your query, or get a default value when that is defined.
suppose your table looks like this
create table Worker (id int not null, WorkingPlace varchar(50) null, SomeValue int not null)
then you cannot insert a row like this
insert into Worker (WorkingPlace) values ('something')
This will fail because you have not provided a value for then column id that is defined as not null, and no value for the column SomeValue because that is also defined as not null
if your table looks like
create table Worker (id int primary key not null identity, WorkingPlace varchar(50) null, SomeValue int not null)
then the statement
insert into Worker (WorkingPlace) values ('something')
Will only fail because there is no value for the column SomeValue.
The column id will get its value from the identity
Solution:
insert into Worker (WorkingPlace, SomeValue) values ('something', 123)
Try this way
DECLARE #Worker TABLE (id int,
WorkingPlace varchar(50),
SomeValue varchar(50))
INSERT INTO #Worker(id,SomeValue)
SELECT w.id, w.wPlace, w.something
FROM [source].[Worker] AS w
Related
i'm trying to have a table with a column that has a default value.
right now i can only get this by having a trigger change the value to the default, is it possible to have it declared on the table right from the start?
Would it be possible to have something like the Identity, where i don't have to pass the value into the insert?
egx: insert into Direct values(2)
and the table would become
id | item
1 | 2
the id = 1, would be the deafult value
thanks in advance!
you can create constraints at time of table creation or later.
create table
#test
(
id int identity(1,2),
name char(255) default newid(),
code int default 2
)
---if a table contains all default values,you can insert like below
insert into #test
default values
updated as per comments:
create table
#test1
(
id int identity(1,2),
name char(255) default newid(),
code int default 2,
notdf int
)
---if a table contains one default value and rest all are default
insert into #test1(notdf)
select 2
Further if you want to add a default value after table creation you can do it like below
create table
tt1
(
valuue int,
address char(2) not null
)
insert into tt1
select 1,'a'
ALTER TABLE tt1 ADD CONSTRAINT test1 DEFAULT null FOR address;
Use default. You can change an existing column by doing:
ALTER TABLE t ADD CONSTRAINT df_t_column DEFAULT 1 for id;
An identity is trickier. I would suggest copying the data over to a temporary table, dropping the table, creating it with an identity column and reloading the data.
I want to create a new column and populate the value of each row in that column with the row number.
This could be achieved in oracle by doing this.
alter table mytable add (myfield integer);
update mytable set myfield = rownum;
How would this be done in SYBASE ASE?
alter table mytable
add id bigint identity not null
That's all. There will be a column id in every row that contains a unique sequence number for that row.
create column table some_names
(ID bigint not null primary key generated by default as IDENTITY,
NAME nvarchar(30));
And now we can do things like this:
insert into some_names (name) values ('Huey');
insert into some_names (name) values ('Dewey');
insert into some_names (name) values ('Louie');
In my case when I tried to do it with identity column time it wasn't able to finish in reasonable time (196400 rows).
Fast and easy way was to create an INT column and fill it up using a temporary variable #id incremented after each row.
This solution finished in ~4 seconds.
alter mytable add myfield INT
DECLARE #id INT
SET #id = 0
UPDATE mytable
SET #id = myfield = #id + 1
You can find more info here: https://www.mssqltips.com/sqlservertip/1467/populate-a-sql-server-column-with-a-sequential-number-not-using-an-identity/
Lets say I have a CREATE TABLE code like this:
CREATE TABLE Test (
ID int NOT NULL IDENTITY(1,1),
SortIndex int,
Name nvarchar(50) NOT NULL
);
I was wondering if it's possible to make a table in MSSQL which had the ability to insert the ID's value into the SortIndex column when I run an INSERT.
So I would run this INSERT:
INSERT INTO Test (Name) VALUES ('Awesome Dude');
Which would normally yield the row:
ID,SortIndex,Name
1,NULL,"Awesome Dude"
But I'd like it to automatically be:
ID,SortIndex,Name
1,1,"Awesome Dude"
Is this even possible by altering the CREATE TABLE script, or do I have to use a TRIGGER?
I would be inclided to take a slightly different approach to this. If you want your SortIndex to default to the ID, but be overridable, I would use a nullable column, and a computed column:
CREATE TABLE Test (
ID int NOT NULL IDENTITY(1,1),
OverrideSortIndex int,
Name nvarchar(50) NOT NULL,
SortIndex AS ISNULL(OverrideSortIndex, ID)
);
If you need to change the sort index for any reason, update the column OverrideSortIndex and this takes precedence.
In SQL Server I have a table as RawTable (temp) which gets fed by a CVS, let's say it has 22 columns in it. Then, I need to copy existing records (ONLY FEW COLUMNs NOT ALL) into another table as Visitors which is not temporary table.
Visitor table has an ID column as INT and that is primary key and incremental.
RawData table
id PK, int not null
VisitorDate Varchar(10)
VisitorTime Varchar(11)
Visitors table
VisitorID, PK, big int, not null
VisitorDate, Varchar(10), null
VisitorTime Varchar(11), null
So I did:
insert into [dbo].[Visitors] ( [VisitorDate], [VisitorTime])
select [VisitorDate], [VisitorTime]
from RawTable /*this is temp table */
Seems SQL Server doesn't like this method so it throws
Msg 515, Level 16, State 2, Line 1
Cannot insert the value NULL into column 'VisitorID', table 'TS.dbo.Visitors'; column does not allow nulls. INSERT fails. The statement has been terminated.
How can I keep Sql Server not to complain about the primary key? this column as you know better will be fed by sql server itself.
Any idea?
Just because your visitors table has an ID column that is the primary key doesn't mean that the server will supply your ID values for you. if you want SQL to provide the ID's then you need to alter the table definition and make the visitorsId column an IDENTITY column.
Otherwise, you can psuedo-create these id's during the insert with the ROW_NUMBER function -
DECLARE #maxId INT;
SELECT #maxId = (SELECT MAX(visitorsId) FROM dbo.visitors);
INSERT INTO [dbo].[Visitors] ( [visitorsId],[VisitorDate], [VisitorTime])
SELECT #maxId + ROW_NUMBER() OVER (ORDER BY visitorDate), [VisitorDate], [VisitorTime]
from RawTable /*this is temp table */
For example: I have COLUMN_PK column of type int identity(1,1) and column COLUMN_NUM pf type int, how could I define default value for COLUMN_NUM - value of COLUMN_PK?
So if I have entity with not specified COLUMN_NUM it will be populated with generated value from COLUMN_PK. But if COLUMN_NUM is specified its value will be used.
Create a 3rd column that is computed
CREATE TABLE MyTable (
COLUMN_PK int NOT NULL identity(1,1) ,
...
COLUMN_NUM_internal int NULL,
COLUMN_NUM AS COALESCE (COLUMN_NUM_internal, COLUMN_PK),
...
)
The PK value is not known until INSERT ( of course). But not before so you have do something like this or use a trigger to update COLUMN_NUM. However, this solution above works for subsequent UPDATEs too with no extra code (i.e. another trigger for UPDATE)
Use computed column and a scalar function as default value.
I would enforce this through a trigger.
create trigger tr_IU_YourTable on YourTable
for insert,update
as
begin
update yt
set column_num = yt.column_pk
from inserted i
inner join YourTable yt
on i.column_pk = yt.column_pk
and yt.column_num is null
end
go
How about having a child table to store just COLUMN_PK and COLUMN_NUM? This table will have a record only if COLUMN_NUM value is specified. Then you can do:
CREATE TABLE Parent (COLUMN_PK int NOT NULL identity(1,1), someCol int NOT NULL)
CREATE TABLE Child (COLUMN_PK int NOT NULL, COLUMN_NUM int NOT NULL)
INSERT INTO Parent (someCol) VALUES (1)
INSERT INTO Parent (someCol) VALUES (2)
INSERT INTO Parent (someCol) VALUES (3)
INSERT INTO Parent (someCol) VALUES (4)
INSERT INTO Parent (someCol) VALUES (5)
INSERT INTO Child VALUES (1, 10)
INSERT INTO Child VALUES (3, 30)
INSERT INTO Child VALUES (5, 50)
SELECT COLUMN_PK,
CASE WHEN EXISTS (SELECT NULL FROM Child WHERE Child.COLUMN_PK = Parent.COLUMN_PK)
THEN (SELECT COLUMN_NUM FROM Child WHERE Child.COLUMN_PK = Parent.COLUMN_PK)
ELSE COLUMN_PK
END
FROM Parent
Using NHibernate to call a stored procedure to insert data, rather than use a direct insert via a .save method could give you more control.