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.
Related
I'm doing a school project about a school theme where I need to create some tables for Students, Classes, Programmes...
I want to add a Group to determined classes with an auto increment in group_id however I wanted the group_id variable to reset if I change any of those attributes(Classes_id,courses_acronym,year_Semesters) how can I reset it every time any of those change??
Here is my table:
CREATE TABLE Classes_Groups(
Classes_id varchar(2),
Group_id INT IDENTITY(1,1),
courses_acronym varchar(4),
year_Semesters varchar(5),
FOREIGN KEY (Classes_id, year_Semesters,courses_acronym) REFERENCES Classes(id,year_Semesters, courses_acronym),
PRIMARY KEY(Classes_id,courses_acronym,year_Semesters,Group_id)
);
Normally, you do not (need to) reset the identity column of a table. An identity column is used to create unique values for every single record in a table.
So you want to generate entries in your groups table based on new entries in your classes table. You might create a trigger on your classes table for that purpose.
Since Group_id is already unique by itself (because of its IDENTITY), you do not need other fields in the primary key at all. Instead, you may create a separate UNIQUE constraint for the combination (Classes_id, courses_acronym, year_Semesters) if you need it.
And if the id field of your classes table is an IDENTITY column too, you could define a primary key in your classes table solely on that id field. And then your foreign key constraint in your new groups table can only include that Classes_id field.)
So much for now. I guess that your database design needs some more additional tuning and tweaking. ;)
where are you setting the values from?, you can have a stored proc and in your query have the columns have an initial value set when stored proc is hit assuming there are values at the beginning
.Then use an IF statement.
declare #initial_Classes_id varchar(2) = --initial value inserted
declare #initial_courses_acronym varchar(4) = --initial value inserted
declare #initial_year_Semesters varchar(5) = --initial value inserted
declare #compare_Classes_id varchar(2) = (select top 1 Classes_id from Classes_Groups order by --PK column desc for last insert); l would add Dateadded and then order with last insert date
declare #compare_courses_acronym varchar(2) = (select top 1 Classes_id from Classes_Groups where Classes_id = #compare_Classes_id);
declare #compare_year_Semesters varchar(2) = (select top 1 Classes_id from Classes_Groups where Classes_id = #compare_Classes_id);
IF (#initial_Classes_id != #compare_Classes_id OR #initial_courses_acronym != #compare_courses_acronym OR #initial_year_Semesters != #compare_year_Semesters)
BEGIN
DBCC CHECKIDENT ('Group_id', RESEED, 1)
Insert into Classes_Groups (courses_acronym,year_Semesters)
values (
courses_acronym,
year_Semesters
)
END
ELSE
BEGIN
Insert into Classes_Groups (courses_acronym,year_Semesters)
values (
courses_acronym,
year_Semesters
)
END
NB: would advice to use int on the primary key. Unless you have a specific purpose of doing so.
If I want to do something relatively complicated - something usually done by a stored procedure. Is it possible to make it automatic using a VIEW?
My specific case:
I want output table = input table A + some rows input table B. In a stored procedure, I can make a copy of table A and then INSERT INTO it, but it's not allowed in a view.
Simplified example:
input table is [test_album], and output table = input table + singer Prince.
--create test data
IF OBJECT_ID('[dbo].[test_album]', 'U') IS NOT NULL
DROP TABLE [dbo].[test_album]
CREATE TABLE [test_album] (
id int not null identity(1, 1) primary key,
singer VARCHAR(50) NULL,
album_title VARCHAR(100) NULL
)
INSERT INTO [test_album] (singer, album_title)
VALUES ('Adale', '19'),
('Michael Jaskson', 'Thriller')
--this can be executed as sql code or in stored proc
SELECT *
INTO [result_table]
FROM [test_album]
INSERT INTO [result_table] ([singer])
VALUES ('Prince')
select *
from [result_table]
--id singer album_title
--1 Adale 19
--2 Michael Jaskson Thriller
--3 Prince NULL
----as expected
But I can do this INSERT INTO inside a view.
Real-life case:
additional singers are in a table [extra_singers]
[test_album] may have many other columns (or schema may change) so it's ideal not to type all column names in the code.
--create test data
IF OBJECT_ID('[dbo].[test_album]', 'U') IS NOT NULL
DROP TABLE [dbo].[test_album]
IF OBJECT_ID('[dbo].[extra_singers]', 'U') IS NOT NULL
DROP TABLE [dbo].[extra_singers]
IF OBJECT_ID('[dbo].[result_table]', 'U') IS NOT NULL
DROP TABLE [dbo].[result_table]
CREATE TABLE [test_album] (
id int not null identity(1, 1) primary key,
singer VARCHAR(50) NULL,
album_title VARCHAR(100) NULL,
many_other_columns VARCHAR(100) NULL
)
INSERT INTO [test_album] (singer, album_title)
VALUES ('Adale', '19'),
('Michael Jaskson', 'Thriller')
CREATE TABLE [extra_singers] (
[id] int not null identity(1, 1) primary key,
[name] VARCHAR(50) NULL )
INSERT INTO [extra_singers] ([name])
VALUES ('Prince'),
('Taylor Swift')
--append [extra_singers] to [test_album]
--this can be executed as sql code or in stored proc
SELECT *
INTO [result_table]
FROM [test_album]
INSERT INTO [result_table] ([singer])
SELECT [name]
FROM [extra_singers]
Is there an alternative to this (that is automatic)?
any help's appreciated. Thank u-
a partial solution I can think of:
create view test_view as
select *
from [test_album]
union all
select 3 as id,
'Prince' as singer,
NULL as album_title
but you have to know all the column names in [test_album] and you can't let column [id] do auto-increment
So you may be misunderstanding what a view does, or what an insert is. A view is simply a wrapper around a single select query. It contains exactly one select statement, and nothing else. An insert permanently adds a row of data to a persisted table. The example you gave where you just union the row you want seems valid enough. And certainly if it's the same row you want every time, you would not want to be inserting (or even trying to insert) that row into the underlying table each time
This raises a couple questions though.
If you're always going to be unioning the same single row every time, why not jut add that row to the table?
If, lets say, you don't want that row in the underlying table, cool. But if it's always the same static values, why do you need to include it in the view? Can't it just be assumed it's there?
If it can't be assume to always be the same, you certainly don't want to be changing the VIEW body every time you need it to change. So if it is going to change and you don't want to insert it into the base table, maybe make a second table containing the values you want appended to the base table in the view. Then union the base table and the "extra values" table together instead of a single, hard coded row constructor.
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 have the following two tables:
CREATE TABLE buildings
(
ID int IDENTITY NOT NULL PRIMARY KEY,
city_ID int NOT NULL REFERENCES(cities),
name char(20) NOT NULL
)
CREATE TABLE cities
(
ID int IDENTITY NOT NULL PRIMARY KEY,
name char(30) NOT NULL
)
INSERT INTO cities (name) VALUES ('Katowice')
Now I need that when I write:
INSERT INTO buildings (city_ID,name) values (1,'bahnhof')
makes the same effect that when I write:
INSERT INTO buildings VALUES ('Katowice','bahnhof')
My purpose is that when I want to add building to a city, I think about city name, not its ID in cities table. But sometimes I remember ID, and then I prefer to use ID. Is it possible without creating a procedure?
I am thinking about appropriate procedure:
CREATE PROCEDURE addbuilding
#city_ID int,
#name char
AS
BEGIN
INSERT INTO buildings (city_ID,name) VALUES (#city_ID,#name)
END
But as we can see above, #city_ID can be only int. Something like union in C++ could be a good solution, but is it possible in SQL?
I'm not sure if SQL procedures support union similarly to C++ as you ask, but my suggestion would be a rather simple one: two procedures.
CREATE PROCEDURE add_building_by_city_id
#city_ID int,
#name char
etc
CREATE PROCEDURE add_building_by_city_name
#city_name char,
#name char
etc
And then you could use whichever one you need. Of course that the second procedure would need a simple SELECT first, to find the city by its name and retrieve its ID.
I've created a insert stored procedure with two tables like in the exapmle:
Table NameAge
CREATE TABLE [dbo].[Assignment3_NameAge]
(
userID int PRIMARY KEY IDENTITY(1,1),
Name varchar(255) NOT NULL,
Age int NOT NULL
)
Table Hobbies
CREATE TABLE [dbo].[Assignment3_Hobbies]
(
hobbiesID int Identity(1,1) Primary Key,
userID int Foreign Key references Assignment3_NameAge(userID),
hobbies varchar(255) NOT NULL,
)
Insert Stored Procedure
CREATE PROCEDURE [dbo].p_Assignment3Join_ins
#Name nvarchar(100),
#Age int,
#Hobbies nvarchar(100)
AS
INSERT INTO [TABLE].[dbo].[Assignment3_NameAge]
([Name]
,[Age])
VALUES (#Name,#Age)
INSERT INTO [TABLE].[dbo].[Assignment3_Hobbies]
([Hobbies])
VALUES (#Hobbies)
The problem is that when i run the stored procedure the table Hobbies has a null value for userid(the foreign key)
What am i doing wrong?
You should provide the key of the Assignment3_NameAge value you want to insert into Assignment3_Hobbies.
If you want the last inserted you can use SCOPE_IDENTITY() from SQL Server(if you're using SQL Server) or equivalent. It will give you the last inserted value from Assignment3_NameAge
I am guessing this is SQL Server based on the IDENTITY column. Correct?
The first insert creates a user, but there is no user ID being set on the insert of the hobby. You need to capture the identity value from the first insert to be used in the second insert. Have you gon over the system functions available?
You're not supplying a value for it, SQL won't automagically fill the value in for you even though you've created a Foreign Key relationship. It's your job to populate the tables.