SQL Lookup List - sql

I have been asked to create a table in SQL and am not sure about one of the table fields.
I have been asked to create a table with the following information:
First Name
Last Name
Three Address Lines
Mobile Phone
Home Phone
Date Modified
Person Category
Comment
This is the description for the Person Category:
Person Category:
Simple Lookup List contained in the database, (ID and Description), can pre-populate this data from the script, no need to edit and update from the VB application. Category descriptions are: Client, Worker, Assessor, and Unknown.
Can someone please explain to me what is needed here?
UPDATE
Here is my current script for the Person table:
CREATE TABLE db_person.Person
(
PersonID NUMBER NOT NULL,
FirstName varchar(50) NOT NULL,
LastName varchar(50) NOT NULL,
AddressLine1 varchar(50),
AddressLine2 varchar(50),
AddressLine3 varchar(50),
MobilePhone varchar(20),
HomePhone varchar(20),
DateModified DATE,
PersonCategory varchar(50),
Comment varchar(8000),
PRIMARY KEY (PersonID)
)
Can I have some help to create the Lookup List for the PersonCategory and to link it into the Person Table?

It means that you need to create another table for the Person Category. Thus a one-to-many relationship between the 2 tables.
Moreover because the description of a person is limited to either Client, Worker, Assessor or Unknown, you should be handle this in your script creation by using the keyword "CHECK".
i.e.
CHECK (Description in ("Client", "Worker", "Assessor", "Unknown"))

First of all you must create the Categories lookup table. You could create it with a script like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [Categories](
[Id] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[Description] [varchar](50) NOT NULL,
CONSTRAINT [PK_Categories] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
ALTER TABLE [Categories] ADD CONSTRAINT [DF_Categories_Id] DEFAULT (newid()) FOR [Id]
GO
and populate it with the 4 descriptions:
INSERT INTO Categories ([Description])
VALUES ('Client')
INSERT INTO Categories ([Description])
VALUES ('Worker')
INSERT INTO Categories ([Description])
VALUES ('Assessor')
INSERT INTO Categories ([Description])
VALUES ('Unknown')
After that, you must create the Persons table, with the constraint with the Categories table:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [Persons](
[Id] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[IdCategory] [uniqueidentifier] NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[FirstAddress] [varchar](250) NULL,
[SecondAddress] [varchar](250) NULL,
[ThirdAddress] [varchar](250) NULL,
[HomePhone] [varchar](50) NULL,
[MobilePhone] [varchar](50) NULL,
[Modified] [datetime] NOT NULL,
[Comment] [varchar](500) NULL,
CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
ALTER TABLE [Persons] ADD CONSTRAINT [DF_Persons_Id] DEFAULT (newid()) FOR [Id]
GO
ALTER TABLE [Persons] WITH CHECK ADD CONSTRAINT [FK_Persons_Categories] FOREIGN KEY([IdCategory])
REFERENCES [Categories] ([Id])
GO
ALTER TABLE [Persons] CHECK CONSTRAINT [FK_Persons_Categories]
GO
Now you have the two tables :)
These scripts run on Microsoft SQL Server.
PS: Best practice is to do another table for multiple addresses and multiple phones ;)
To retrieve data with the SELECT, you could do:
SELECT FirstName, LastName, Description AS Category
FROM Persons INNER JOIN
Categories ON Categories.Id = Persons.IdCategory
If you're using NUMBER for the IDs, change the IdCategory datatype in NUMBER. After that, the storedprocedure could be like:
CREATE PROCEDURE [AddPerson]
(
#Category varchar(50),
#FirstName varchar(50),
#LastName varchar(50),
#FirstAddress varchar(250) = NULL,
#SecondAddress varchar(250) = NULL,
#ThirdAddress varchar(250) = NULL,
#HomePhone varchar(50) = NULL,
#MobilePhone varchar(50) = NULL,
#Comment varchar(500) = NULL
)
AS BEGIN
Declare #idCategory NUMBER
Set #idCategory = SELECT Id FROM Categories WHERE Description = Category
INSERT INTO Persons ([IdCategory], [FirstName], [LastName],
[FirstAddress],
[SecondAddress],
[ThirdAddress],
[HomePhone],
[MobilePhone],
[Modified],
[Comment])
VALUES (#idCategory,
#FirstName,
#LastName,
#FirstAddress,
#SecondAddress,
#ThirdAddress,
#HomePhone,
GETDATE(),
#MobilePhone,
#Comment)
END
GO
I'm sorry if this codes contains some errors but I wrote it with notepad :)

Related

Trigger not firing for instead of insert SQL Server

I am trying to create a trigger to convert a value from varchar to varbinary.
The creation of the trigger is successful. However it is not firing against an insert query.
Trigger code:
CREATE TRIGGER HashPassword
ON Users
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Users (Username, [Password], FirstName, LastName, RoleID)
SELECT
i.Username,
CONVERT(varbinary(max), EncryptByPassPhrase('iskam_6_za_bazata_moje_i_za_springa', i.[Password]), 2),
i.FirstName, i.LastName, i.RoleID
FROM
inserted AS i
END
Users table:
CREATE TABLE [dbo].[Users]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Username] [varchar](255) NOT NULL,
[Password] [varbinary](max) NOT NULL,
[FirstName] [nvarchar](255) NOT NULL,
[LastName] [nvarchar](255) NOT NULL,
[RoleID] [int] NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Users] WITH CHECK
ADD CONSTRAINT [FK_Users.RoleID]
FOREIGN KEY([RoleID]) REFERENCES [dbo].[Roles] ([Id])
GO
ALTER TABLE [dbo].[Users] CHECK CONSTRAINT [FK_Users.RoleID]
GO
I tried executing this query:
INSERT INTO Users (Username, [Password], FirstName, LastName, RoleID)
VALUES ('martini', 'parola', 'martin', 'atanasov', 4)
But the result was an error:
Implicit conversion from data type varchar to varbinary(max) is not allowed. Use the CONVERT function to run this query.
You can't insert a varchar into a varbinary max column. So this
INSERT INTO Users(Username,[Password],FirstName,LastName,RoleID)
VALUES('martini','parola','martin','atanasov',4)
should be
INSERT INTO Users(Username,[Password],FirstName,LastName,RoleID)
VALUES('martini', cast(N'parola' as varbinary(max)),'martin','atanasov',4)
Or you create a view on Users that performs the varbinary>nvarchar cast and put your instead of trigger on that.

Trying to write a stored procedure with a Identity column to create my table values

I am trying to write a stored procedure that creates a new row of data in my table that has an Identity column. I can't figure out what I'm doing wrong to get it to store my data in the table.
Here is my table
CREATE TABLE [Promotional].[Proposals]
(
[Proposal_Uid] [int] IDENTITY(1,1) NOT NULL,
[Prime_Contract] [nvarchar](30) NULL,
[Sub_Contract] [nvarchar](30) NULL,
[Po_Id] [nvarchar](30) NULL,
[Proposal_Title] [nvarchar](50) NULL,
[Client_Name] [nvarchar](40) NULL,
[Client_Code] [nvarchar](20) NULL,
[Total_Proposal_Amount] [decimal](18, 2) NULL,
[ODC_Amount] [decimal](18, 2) NULL,
[Manager_Name] [nvarchar](30) NULL,
[Admin] [nvarchar](30) NULL,
[Due_Date] [date] NULL,
[Start_Date] [date] NULL,
[End_Date] [date] NULL,
[Proposal_Number] [nvarchar](20) NULL,
[Contract_Type] [nvarchar](16) NULL,
CONSTRAINT [Proposal_Uid]
PRIMARY KEY CLUSTERED ([Proposal_Uid] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Here is my stored procedure:
ALTER PROCEDURE [Promotional].[Proposals_Create]
(#Prime_Contract nvarchar(30),
#Sub_Contract nvarchar(30),
#Po_Id nvarchar(30),
#Proposal_Title nvarchar(50),
#Client_Name nvarchar(40),
#Client_Code nvarchar(20),
#Total_Proposal_Amount decimal(18,2),
#ODC_Amount decimal(18,2),
#Manager_Name nvarchar(30),
#Admin nvarchar(30),
#Due_Date date,
#Start_Date date,
#End_Date date,
#Proposal_Number nvarchar(20),
#Contract_Type nvarchar(16),
#NewId int output)
AS
BEGIN
IF #NewId IS NULL
BEGIN
INSERT INTO Promotional.Proposals (Prime_Contract, Sub_Contract, Po_Id, Proposal_Title, Client_Name, Client_Code,
Total_Proposal_Amount, ODC_Amount, Manager_Name, Admin, Due_Date, Start_Date, End_Date, Proposal_Number, Contract_Type)
VALUES (#Prime_Contract, #Sub_Contract, #Po_Id, #Proposal_Number, #Client_Name, #Client_Code,
#Total_Proposal_Amount, #ODC_Amount, #Manager_Name, #Admin, #Due_Date, #Start_Date, #End_Date,
#Proposal_Number, #Contract_Type)
SET #NewId = SCOPE_IDENTITY()
END
RETURN #NewId
END
GO
I know it's something small I missed. But, my OUTCOME is that when you run the procedure, it inserts the values in the correct columns, and the primary key is auto updated without having to stick your own value into the statement. My execution of the statement would be as follows
EXEC Promotional.Proposals_Create 'hj','fd','fd','fd','fd','fd','0.23','1.24','fd','fd','2020/08/30','2020/08/30','2020/08/30','fd','fd';
And I get this error:
Msg 201, Level 16, State 4, Procedure Promotional.Proposals_Create, Line 0 [Batch Start Line 0]
Procedure or function 'Proposals_Create' expects parameter '#NewId', which was not supplied.
I shouldn't have to provide that parameter because it should auto update with my PK which is Proposal_Uid. Or do I have to make my Proposal_Uid the value returned from ScopeIdentity?
#NewID should not be a parameter of the procedure since it is an IDENTITY column.
You can get the stored procedure to return the generated id by providing an output variable to store its content. This behaviour is also documented here.
declare #test int;
EXEC Proposals_Create 'hj','fd','fd','fd','fd','fd','0.23','1.24','fd','fd',
'2020/08/30','2020/08/30','2020/08/30','fd','fd', #test OUTPUT;
select #test as 'new_identity';
set #test = null; -- because of the IF statement in your procedure...
EXEC Proposals_Create 'hj','fd','fd','fd','fd','fd','0.23','1.24','fd','fd',
'2020/08/30','2020/08/30','2020/08/30','fd','fd', #test OUTPUT;
select #test as 'new_identity';
The selects return 1 and 2 respectively.
Fiddle (Remark: schema name removed in code above and in fiddle).

Write a trigger to update the columnB in TableB when the ColumnA in TableA are updated based on the common column in both the tables

CREATE TABLE [dbo].[USERS]
(
[USER_NAME] [nvarchar](64) NOT NULL,
[EMAIL_ADDRESS] [nvarchar](256) NULL,
[REGISTERED_DATE] [datetime] NOT NULL,
[FULL_NAME] [nvarchar](256) NOT NULL,
[MANAGER] [nvarchar](64) NULL,
[DEPARTMENT] [nvarchar](256) NULL,
[TITLE] [nvarchar](64) NULL,
PRIMARY KEY CLUSTERED ([USER_NAME] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
This is my table and I want the trigger to fire when the manager column is updated and the same values of the manage have to update on the another table based on the USER_NAME column.
i tried the the below trigger but it is not working.
Create TRIGGER [dbo].[UpdateManager]
ON [dbo].[USERS]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
declare #USER_NAME as nvarchar
declare #MANAGER as nvarchar
if(update(MANAGER))
begin
select #USER_NAME = USER_NAME from deleted
select #manager = Manager from deleted
update [dbo].[USERS_TEST] set MANAGER=#MANAGER where USER_NAME= #USER_NAME
end
END
You have two MAJOR issues in your trigger:
As mentioned in a comment, deleted can have multiple rows and you don't take that into account.
nvarchar has no length; the default in this case is a length of 1.
I suspect that the query you want is:
update ut
set MANAGER = d.MANAGER
from [dbo].[USERS_TEST] ut join
deleted d
on ut.USER_NAME = d.USER_NAME ;

How to insert Foreignkey value into a table which doesnt exist yet

I have a situation, I have two tables namely ,User and Company .
Here is my User table :
CREATE TABLE [dbo].[User](
[UserId] [int] IDENTITY(1,1) NOT NULL,
[UserName] [nvarchar](500) NOT NULL,
[Password] [nvarchar](500) NOT NULL,
[CompanyId] [int] NULL,
[LastModUserId] [int] NOT NULL,
[LastModDttm] [datetime] NOT NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[User] WITH CHECK ADD CONSTRAINT [FK_User_Company] FOREIGN KEY([CompanyId])
REFERENCES [dbo].[Company] ([CompanyId])
GO
ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_User_Company]
GO
ALTER TABLE [dbo].[User] WITH CHECK ADD CONSTRAINT [FK_User_User1] FOREIGN KEY([LastModUserId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_User_User1]
GO
Here is my Company Table :
CREATE TABLE [dbo].[Company](
[CompanyId] [int] IDENTITY(1,1) NOT NULL,
[CompanyName] [nvarchar](500) NOT NULL,
[Address1] [nvarchar](500) NULL,
[Address2] [nvarchar](500) NULL,
[LastModUserId] [int] NOT NULL,
[LastModDttm] [datetime] NOT NULL,
CONSTRAINT [PK_Company] PRIMARY KEY CLUSTERED
(
[CompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Company] WITH CHECK ADD CONSTRAINT [FK_Company_User] FOREIGN KEY([LastModUserId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[Company] CHECK CONSTRAINT [FK_Company_User]
GO
My problem :
I want to create a company record,I haven't created a user yet.When I Insert into the LastModUserId columun it will throw the error "Cannot Insert the value NULL into column 'LastModUserId' ,table MYDb.dbo.Company' , column does not allow nulls.INSERT fails.
If I try to insert a record into the User Table ,there is also the same problem ,there is CompanyId column,which doesn't allow nulls either
How do I handle this situation ?
Disable constraint to enter super record.
ALTER TABLE [User] NOCHECK CONSTRAINT [FK_User_User1];
GO
ALTER TABLE [User] NOCHECK CONSTRAINT [FK_User_Company];
GO
DECLARE #USERID AS INT, #COMPANYID AS INT;
SELECT #USERID = 1, #COMPANYID = 1;
SET IDENTITY_INSERT [User] ON;
INSERT INTO [User](
[UserId],
[UserName],
[Password],
[CompanyId],
[LastModUserId],
[LastModDttm]
)
select
#USERID,
'Super',
'Passw0rd',
1,
1,
getdate();
SET IDENTITY_INSERT [User] OFF;
SET IDENTITY_INSERT [Company] ON;
insert into [Company](
[CompanyId],
[CompanyName],
[Address1],
[Address2],
[LastModUserId],
[LastModDttm])
select
#COMPANYID,
'cOMANY a',
'Address 1',
'Address 2',
#USERID,
getdate();
SET IDENTITY_INSERT [Company] OFF;
go
ALTER TABLE [User] CHECK CONSTRAINT [FK_User_User1];
GO
ALTER TABLE [User] CHECK CONSTRAINT [FK_User_Company];
GO

Violation of UNIQUE KEY constraint during SQL update

I have a simple database table (SQL Server 2008 R2 Express), which has a definition as follows:
ID INT Auto Inc, PK
Name VARCHAR(64) Unique Key
Telephone VARCHAR(128)
I have a stored procedure which I execute to update records within the table which basically does the following:
UPDATE customers
SET Name = #name, Telephone = #Telephone
WHERE id = #id
Currently, I have two entries in the table
ID Name Telephone
1 Fred 01234 567890
2 John 09876 543210
When I call my stored procedure to update the telephone number for John, the SQL that is effectively executed is
UPDATE customers
SET Name = 'John', Telephone = '02468 135790'
WHERE id = 2
This generates a UNIQUE KEY violation on the Name field. Now as the Name field doesn't actually change, why does this occur?
As all database actions are being handled by my app using stored procedures, I could fix this by removing the constraint, and modifying the stored procedures to manually enforce the constraint, but this just seems wrong.
Given that my table actually has many more fields, there must be a generic work around that I can employ to prevent these false constraint problems, without having to generate numerous stored procedures to update specific fields?
Edit: The above table was simplified to keep the question more manageable, I'm pretty sure I've not missed anything important, but for info, the actual definition of the table is as follows
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[companies](
[id] [int] IDENTITY(1,1) NOT NULL,
[typeId] [int] NOT NULL,
[name] [varchar](64) NOT NULL,
[displayName] [varchar](128) NOT NULL,
[deliveryAddress] [varchar](1024) NOT NULL,
[invoiceAddress] [varchar](1024) NOT NULL,
[telephone] [varchar](64) NOT NULL,
[fax] [varchar](64) NOT NULL,
[email] [varchar](256) NOT NULL,
[website] [varchar](256) NULL,
[isActive] [bit] NOT NULL,
CONSTRAINT [PK_companies] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [Unique Display Name] UNIQUE NONCLUSTERED
(
[displayName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [Unique Name] UNIQUE NONCLUSTERED
(
[name] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[companies] WITH CHECK ADD CONSTRAINT [Company Type] FOREIGN KEY([id])
REFERENCES [dbo].[companyTypes] ([id])
GO
ALTER TABLE [dbo].[companies] CHECK CONSTRAINT [Company Type]
GO
...and the stored procedure
ALTER PROCEDURE UpdateCompany
#id INT,
#typeId INT,
#name VARCHAR(64),
#displayName VARCHAR(128),
#deliveryAddress VARCHAR(1024),
#invoiceAddress VARCHAR(1024),
#telephone VARCHAR(64),
#fax VARCHAR(64),
#email VARCHAR(256),
#website VARCHAR(256),
#isActive BIT
AS
BEGIN
UPDATE companies
SET typeid = #typeid,
name = #name,
displayname = #displayname,
deliveryAddress = #deliveryAddress,
invoiceAddress = #invoiceAddress,
telephone = #telephone,
fax = #fax,
email = #email,
website = #website,
isActive = #isActive
EXEC GetCompany #id
END
GO
You're missing the WHERE in your UPDATE statement so currently it will try and update all rows in the table with the same values.