I created a new database called sample1. In it I created 3 tables: "address, contact and buyer"
CREATE TABLE address
(
address_id int NOT NULL identity(1,1) primary key,
street_name varchar(30)
);
CREATE TABLE contact
(
contact_id int NOT NULL identity(1,1) primary key,
phone_num varchar(20) NOT NULL,
address_id int NOT NULL foreign key REFERENCES address(address_id)
);
CREATE TABLE buyer
(
username char(20) NOT NULL primary key,
name char(40) NOT NULL,
contact_id int NOT NULL foreign key REFERENCES contact(contact_id)
);
The tables were created successfully, now I'm trying to create a stored procedure as follows:
create procedure csc
(
#username char(20),
#address_id int,
#contact_id int
)
as
set nocount on;
insert into [dbo].[buyer] values (#username);
insert into [dbo].[address_id] values (#address_id);
insert into [dbo].[contact_id] values (#contact_id);
go
But I get the following errors:
Msg 137, Level 15, State 2, Line 4
Must declare the scalar variable "#username".
Msg 137, Level 15, State 2, Line 10
Must declare the scalar variable "#username".
Msg 137, Level 15, State 2, Line 11
Must declare the scalar variable "#address_id".
Msg 137, Level 15, State 2, Line 12
Must declare the scalar variable "#contact_id".
My questions / errors:
Are my tables logical? Should I be using buyer username as the PK for address / contact ID (my teacher suggested this, but I think it's bad practice)
When creating my procedure, I get red lines on [dbo].[buyer], [dbo].
[address_id], [dbo].[contact_id], can I ignore these?
How in the world do I fix the errors?
Thanks in advance.
1, are my tables logical? should I be using buyer username as the PK
for address / contact ID (my teacher suggested this, but I think it's
bad practice)
It depends whether a buyer is always defined by their username and that won't get updated. This is an age old debate between natural and surrogate keys, you can have a google and find some pretty convincing arguments for either side. If you think it's bad practice then you'll need to be able to explain why you think this. I would certainly avoid using the char datatype unless you really wanted to use it, it will blank pad your data up to it's specified length.
2, when creating my procedure, I get red lines on [dbo].[buyer],
[dbo]. [address_id], [dbo].[contact_id], can I ignore these?
That's because when SSMS last looked, those tables do not exist. If you press CTRL+SHIFT+R, you will refresh intelligence and it will check again. It'll still fail though because address_id nor contact_id are tables.
3, how in the world do I fix the errors?
You fix the table names. But once you've done that you'll reach another error as you aren't specifying what column your values should be inserted into and there are multiple it can use. The problem is that your code wants to insert your primary key columns but with no additional data - so really you need to complete your code so that all the required data is input and the columns they are inserting into are explicitly mentioned.
e.g.
insert into [dbo].[buyer] (username, name, contact_id) values (#username, #name, #contact_id);
But.. you are inserting the contact row at the same time and you've declared it as an identity column, should you really know the value of this column already or should you be inserting the other values into the table and generating a new contact_id with it?
Perhaps your procedure should really start
create procedure csc(
#username char(20),
#name char(40),
#street_name varchar(30),
#phone_num varchar(20)
)
And then build up your insert statements from that data. Something like:
as
set nocount on;
declare #address_id int;
declare #contact_id int;
insert into [dbo].[address] (street_name) values (#street_name);
set #address_id = SCOPE_IDENTITY() ;
insert into [dbo].contact (phone_num, address_id) values (#phone_num, #address_id);
set #contact_id = SCOPE_IDENTITY() ;
insert into [dbo].[buyer] (username, name, contact_id) values (#username, #name, #contact_id);
go
And to demo:
exec csc 'andy','andy','Nice Road',42
select * from buyer;
select * from contact;
select * from address;
username name contact_id
-------------------- ---------------------------------------- -----------
andy andy 3
(1 row affected)
contact_id phone_num address_id
----------- -------------------- -----------
3 42 3
(1 row affected)
address_id street_name
----------- ------------------------------
3 Nice Road
(1 row affected)
It looks like you've got a couple of typos. Try it like this
create procedure csc
#username char(20),
#address_id int,
#contact_id int
as
set nocount on;
insert into [dbo].[buyer] values (#username);
insert into [dbo].[address] values (#address_id);
insert into [dbo].[contact] values (#contact_id);
go
Use a begin/end block:
create procedure csc (
#username char(20),
#address_id int,
#contact_id int
) as
begin
set nocount on;
insert into [dbo].[buyer] values (#username);
insert into [dbo].[address_id] values (#address_id);
insert into [dbo].[contact_id] values (#contact_id);
end;
go
Related
Maybe someone can tell me why this is happening. I wrote this stored procedure:
CREATE PROCEDURE Newmessages
#Message_id VARCHAR(20)
,#First_name VARCHAR(20)
,#Last_name VARCHAR(20)
,#Email VARCHAR(20)
,#Phone VARCHAR(20)
,#Postal_code VARCHAR(20)
,#Notification_1 BIT
,#Notification_2 BIT
,#Own_Pets BIT
,#Organization_Id VARCHAR(20)
,#Animal_Id VARCHAR(20)
AS
INSERT INTO [dbo].[Messages]
VALUES (#Message_id, #First_name, #Last_name, #Email, #Phone,
#Postal_code, #Notification_1, #Notification_2, #Own_Pets,
#Organization_Id, #Animal_Id)
Now I'm trying to check it by inserting:
exec Newmessages '64654', 'Kelli', 'Adkins', 'acprthvs.bpuzcnt#gmail.com', '478-6273327', 'SR5 2QF', 'False', 'False', 'False', '91839', '40550'
and I get:
Msg 547, Level 16, State 0, Procedure Newmessages, Line 4 [Batch Start Line 0] > The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Messages__Email__3D9E16F4". The conflict occurred in database "Petfinder", table "dbo.Users", column 'Email'.
Thing is, I checked and I do have the email I'm trying to insert in the Users table (which is the error).
Here I checked that it does exist in dbo.Users:
Does anyone know why this is still happening?
The email address you're trying to insert is acprthvs.bpuzcnt#gma, which doesn't exist in your table.
CREATE PROCEDURE Newmessages
...
,#Email VARCHAR(20)
...
The email address you'd like to enter is 26 characters long.
Use an explicit column list on the INSERT to map the columns explicitly:
INSERT INTO [dbo].[Messages] (Message_ID,First_Name, Last_name, Email, Phone, ...)
VALUES (
#Message_id
,#First_name
,#Last_name
,#Email
,#Phone
,#Postal_code
,#Notification_1
,#Notification_2
,#Own_Pets
,#Organization_Id
,#Animal_Id
)
So I'm getting a slew of errors
(1 row(s) affected) Msg 2812, Level 16, State 62, Line 48 Could not
find stored procedure 'AddPartner'. Msg 2812, Level 16, State 62, Line
49 Could not find stored procedure 'AddPartner'. Msg 2812, Level 16,
State 62, Line 50 Could not find stored procedure 'AddPartner'.
(1 row(s) affected)
(1 row(s) affected) Msg 547, Level 16, State 0, Procedure AddAnswer,
Line 114 The INSERT statement conflicted with the FOREIGN KEY
constraint "FK__Answers__partner__145C0A3F". The conflict occurred in
database "SurveyDb", table "dbo.Partners", column 'id'. The statement
has been terminated. Msg 547, Level 16, State 0, Procedure AddAnswer,
Line 114 The INSERT statement conflicted with the FOREIGN KEY
constraint "FK__Answers__partner__145C0A3F". The conflict occurred in
database "SurveyDb", table "dbo.Partners", column 'id'. The statement
has been terminated. Msg 547, Level 16, State 0, Procedure AddAnswer,
Line 114 The INSERT statement conflicted with the FOREIGN KEY
constraint "FK__Answers__partner__145C0A3F". The conflict occurred in
database "SurveyDb", table "dbo.Partners", column 'id'. The statement
has been terminated. Msg 547, Level 16, State 0, Procedure AddAnswer,
Line 114 The INSERT statement conflicted with the FOREIGN KEY
constraint "FK__Answers__partner__145C0A3F". The conflict occurred in
database "SurveyDb", table "dbo.Partners", column 'id'. The statement
has been terminated.
and I think they all originate from the first 3 errors about AddPartner, however I cannot figure out the exact source of the problem as I've looked over my syntax plenty of times. On a related note, does there exist some sort of online tool that can help one get hints for debugging SQL errors?
-- Create database for all information
-- needed in the application, set as context
CREATE DATABASE SurveyDb;
GO
USE SurveyDb;
-- Create surveys table
GO
CREATE TABLE Surveys (
id INT IDENTITY(1,1),
title NVARCHAR(100) NOT NULL,
PRIMARY KEY (id)
);
GO
-- Create sprocs for adding and deleting surveys
CREATE PROCEDURE AddSurvey
#title NVARCHAR(100)
AS
INSERT INTO Surveys (title) VALUES (#title)
GO
CREATE PROCEDURE DeleteSurvey
#id INT
AS
DELETE FROM Surveys WHERE id=#id
GO
-- Seed the surveys table with 1 sample survey
EXEC AddSurvey #title = "Survey Numero Uno";
GO
-- Create partners table
CREATE TABLE Partners (
id INT IDENTITY(1,1),
name NVARCHAR(50) NOT NULL,
PRIMARY KEY (id)
);
GO
-- Create sprocs for adding and deleting partners
CREATE PROCEDURE AddParter
#name NVARCHAR(50)
AS
INSERT INTO Partners (name) VALUES (#name)
GO
CREATE PROCEDURE DeletePartner
#id INT
AS
DELETE FROM Partners WHERE id=#id
GO
-- Seed the partners table with a few samples
EXEC AddPartner #name = 'Haliburton';
EXEC AddPartner #name = 'Berkshite Hathaway';
EXEC AddPartner #name = 'Infosys';
GO
-- Create questions table. Questions are associated with
-- a particular survey. If the survey is deleted then so
-- are all associated questions.
CREATE TABLE Questions (
id INT IDENTITY(1,1),
survey_id INT,
qtext NVARCHAR(300) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (survey_id) REFERENCES Surveys(id) ON DELETE CASCADE
);
GO
-- Create sprocs for adding and deleting questions.
CREATE PROCEDURE AddQuestion
#survey_id INT,
#qtext NVARCHAR(300)
AS
INSERT INTO Questions (survey_id, qtext) VALUES (#survey_id, #qtext)
GO
CREATE PROCEDURE DeleteQuestion
#id INT
AS
DELETE FROM Questions WHERE id=#id
GO
-- Seed the questions table with sample questions.
EXEC AddQuestion #survey_id = 1, #qtext = 'What is the average velocity of an African swallow?';
EXEC AddQuestion #survey_id = 1, #qtext = 'How hot is she, on a scale of 1.0-100.0?';
GO
-- Create table for answers. Answers are associated with both
-- a question and a partner. If either the question or partner
-- is deleted then so are all associated answers.
CREATE TABLE Answers (
id INT IDENTITY (1,1),
question_id INT,
partner_id INT,
val DECIMAL NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (question_id) REFERENCES Questions(id) ON DELETE CASCADE,
FOREIGN KEY (partner_id) REFERENCES Partners(id) ON DELETE CASCADE
);
GO
-- Create sprocs for adding and deleting answers.
CREATE PROCEDURE AddAnswer
#question_id INT,
#partner_id INT,
#val DECIMAL
AS
INSERT INTO Answers (question_id, partner_id, val) VALUES (#question_id, #partner_id, #val)
GO
CREATE PROCEDURE DeleteAnswer
#id INT
AS
DELETE FROM Answers WHERE id=#id
GO
-- Seed the questions table with sample answers.
EXEC AddAnswer #question_id = 1, #partner_id = 1, #val = 23.3;
EXEC AddAnswer #question_id = 2, #partner_id = 1, #val = 99.5;
EXEC AddAnswer #question_id = 1, #partner_id = 2, #val = 0.12345;
EXEC AddAnswer #question_id = 2, #partner_id = 2, #val = 0.19;
The problem is in the AddAnswer procedure. You're adding partner id's that don't exist in the partner table, so referential integrity fails. Look in your partner table ( select * from partners ) and see what the id's are.
Other than that, I'd say that 1) you need to add some checking before inserting rows. If you try to add 'Berkshire Hathaway' twice, it's going to error. Check first and you don't have that problem:
if not exists ( select * from partners where [name] = #name )
begin
INSERT INTO Partners (name) VALUES (#name)
end
Also: you should really consider not using a column named name - call it PartnerName or something, sure, but having random name columns doesn't help readability and may cause syntax-checking problems down the road.
EDIT: Or, as Jamie points out, correct the typo in the stored procedure name.
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 have two tables:
Rooms:
ID (auto-incrementing primary key, int)
Topic (varchar(50))
MangerId (varchar(50))
Rooms_Users:
UserId (varchar(50))
RoomId (varchar(50))
both fields together are the primary key
I want to insert a room but I also must insert the manger to the table rooms_users.
Here is what I have so far:
ALTER PROCEDURE [dbo].[Creat_Room] #MangerId varchar(50) ,#Topic varchar(50)
AS
BEGIN
SET NOCOUNT
insert into Rooms(ManagerId,Topic) values(#MangerId,#Topic)
insert into Rooms_Users(UserId,RoomId) values(#MangerId,?????????????)
END
The ????????????? is the problem: I don't know what to put here i want to put the roomid i insert above.
You can use the output clause. Look at MSDN here: OUTPUT Clause (Transact-SQL)
Example:
declare #tbl table
(
NewID int
)
insert into Rooms(ManagerId,Topic)
output inserted.ID into #tbl
values(#MangerId,#Topic)
Then the table variable will contains the new id given to the row you inserted
Use the SCOPE_IDENTITY() function:
ALTER PROCEDURE [dbo].[Create_Room]
#ManagerId varchar(50),
#Topic varchar(50)
AS
BEGIN
DECLARE #NewRoomID INT
insert into Rooms(ManagerId, Topic) values(#MangerId, #Topic)
SELECT #NewRoomID = SCOPE_IDENTITY()
insert into Rooms_Users(UserId, RoomId) values(#ManagerId, #NewRoomID)
END
This function will return the last inserted IDENTITY value in this particular scope - the scope of your stored procedure.
I have an issue with the below stored procedure. It runs fine as long as I don't uncomment the last insert INSERT. If I were to uncomment the last INSERT, I get the following error:
Msg 547, Level 16, State 0, Procedure
InsertRecipeWithTags, Line 42 The
INSERT statement conflicted with the
FOREIGN KEY constraint
"FK_Tag_TagRecipe". The conflict
occurred in database "RecipeBox",
table "RecipeDetails.Tag", column
'tagID'. The statement has been
terminated.
For clarification, I have three tables:
recipe(id, title, introduction, directions)
recipeTag(id, recipeID, tagID)
tag(id, name)
So if I try to insert into the recipeTag table I get the above error. Please advise.
Thanks.
CREATE PROCEDURE [RecipeDetails].[InsertRecipeWithTags]
/*
variables that map to columns
*/
#title varchar(50),
#intro varchar(255),
#directions varchar(2200),
#ingredients varchar(2200),
#difficulty varchar(6), /*need check constraint setting difficulty to "beginner" "medium" or "expert"*/
#prepTimeHour tinyint,
#prepTimeMinute tinyint,
#inactiveTimeHour tinyint,
#inactiveTimeMinute tinyint,
#servings tinyint,
#photo varbinary(MAX),
#tagName varchar(50),
#tagdescription varchar(255)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #RecipeID int, #TagID int
INSERT INTO RecipeDetails.Recipe (title, intro,directions, ingredients, difficulty,
prepTimeHour, prepTimeMinute, inactiveTimeHour, inactiveTimeMinute, servings, photo)
VALUES (#title, #intro,#directions, #ingredients, #difficulty, #prepTimeHour, #prepTimeMinute,
#inactiveTimeHour, #inactiveTimeMinute, #servings, #photo)
SELECT #RecipeID=SCOPE_IDENTITY()
SELECT * FROM RecipeDetails.Recipe WHERE recipeID = #RecipeID;
INSERT INTO RecipeDetails.Tag (name, description)
VALUES (#tagName, #tagdescription)
SELECT #TagID=SCOPE_IDENTITY()
SELECT * FROM RecipeDetails.Tag WHERE tagID = #TagID;
/*INSERT INTO RecipeDetails.TagRecipe (tagID, recipeID)
VALUES (#RecipeID, #TagID)*/
END
Reverse the order?
INSERT INTO RecipeDetails.TagRecipe (tagID, recipeID)
VALUES (#TagID, #RecipeID)
You had then the wrong way around