SQL Create table in database ssms - sql

I would like to create a database with a couple tables in it. I am using SSMS and it is easy enough to accomplish said task by right-click creating, but I would like to use query/command line (not sure how to phrase that).
Create a database and table
CREATE DATABASE test_employees;
CREATE TABLE dbo.EmployeesBasicInfo
(
MyKeyField VarChar(8) PRIMARY KEY,
FirstName VarChar(30) NOT NULL,
LastName VarChar(50) NOT NULL,
DateStarted DateTime NOT NULL,
Age Int NOT NULL,
ModifiedDate DateTime NULL
);
But I have no idea where the table goes or how to move/link it to database test_employees.
Also, if you feel ambition in answering my question then the next step is to auto-generate data for all fields. Any links you could provide would be helpful. And, if anything I'm doing is not best-practice please let me know - I'm just getting into SQL.

After you've created the database you need to
Use test_employees
Go
This sets your current working database for subsequent statements.
Alternatively you can qualify your create table with the database name
Create Table test_employees.dbo.EmployeesBasicInfo (
MyKeyField varchar(8) primary key,
FirstName varchar(30) not null,
LastName varchar(50) not null,
DateStarted DateTime not null,
Age int not null,
ModifiedDate datetime null
);
You've probably created this table in your default database, which may well be master.
Also for any recent version of SQL Server, consider using datetime2 instead of datetime (or date if you don't need the time component). It's better in all respects.

Here is some code to create a table 1st and then you can add some test data into it to practice with .......
TO CREATE A TABLE :
Create Table dbo.BasicInfo (
MyKeyField INT primary key IDENTITY(1,1),
FirstName varchar(30) not null,
LastName varchar(50) not null,
DateStarted DateTime not null,
Age int not null,
ModifiedDate datetime null
)
GO
TO ADD PRACTICE DATA:
DECLARE #Value INT = 1
WHILE #Value <= 100
BEGIN
INSERT INTO dbo.BasicInfo (FirstName, LastName, DateStarted, Age, ModifiedDate)
VALUES ('First_Name_' + CAST(#Value AS VARCHAR), 'Last_Name_'+ CAST(#Value AS VARCHAR), DATEADD(DAY, -CONVERT(INT, (5000+1)*RAND()), GETDATE()),
18 + CONVERT(INT, (30-10+1)*RAND()), DATEADD(DAY, 10 + (30-10)*RAND() ,DATEADD(DAY, -CONVERT(INT, (5000+1)*RAND()), GETDATE())))
SET #Value = #Value + 1
END
if you want to add more then 100 rows in your table just replace the number or rows you wish to add to your table with 100 in this code

Related

Why am I getting "Error converting data type varchar to int."

I am creating a mock database for a fictional gym. I have 3 relevant tables: Program, Workouts and Exercises (see below). Each Program contains one or many Workouts and each Workout contains one or many Exercises. I am trying to create a stored procedure to add rows to these three tables. I keep getting the error "Error converting data type varchar to int.". I can't understand why because the variable datatypes all match the datatypes in the tables (as far as I can see).
CREATE TABLE [Program]
(
[ProgramID] INT IDENTITY(1,1),
[MemberNumber] INT,
[TrainerID] INT,
[ProgramStartDate] DATE,
[TrainerReviewDate] DATE,
[Active] CHAR(1),
PRIMARY KEY ([ProgramID]),
FOREIGN KEY ([MemberNumber])
REFERENCES [Members] ([MemberNumber])
ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY ([TrainerID])
REFERENCES [Trainers] ([TrainerID])
ON DELETE SET NULL ON UPDATE CASCADE
);
CREATE TABLE [Workouts]
(
[WorkoutID] INT IDENTITY(1,1),
[Description] VARCHAR(50),
[Day] VARCHAR(10),
[ProgramID] INT,
PRIMARY KEY ([WorkoutID]),
FOREIGN KEY ([ProgramID])
REFERENCES [Program] ([ProgramID])
ON DELETE SET NULL ON UPDATE CASCADE
);
CREATE TABLE [Exercise]
(
[ExerciseID] INT IDENTITY(1,1),
[ExerciseType] VARCHAR(30),
[Equipment] VARCHAR(30),
[Sets] INT,
[Reps] INT,
[WorkoutID] INT,
PRIMARY KEY ([ExerciseID]),
FOREIGN KEY ([WorkoutID])
REFERENCES [Workouts] ([WorkoutID])
ON DELETE SET NULL ON UPDATE CASCADE
)
/*Description: This stored procedure adds a new program with workout/exercise details. */
CREATE PROCEDURE usp_New_Program_4 (
#MemberNumber int,
#TrainerID int,
#ProgramStartDate date,
#TrainerReviewDate date,
#Active char(1),
#Description varchar(50),
#Day varchar(10),
#ProgramID int = SCOPE_IDENTITY,
#ExerciseType_1 varchar(30),
#Equipment_1 varchar(30),
#Sets_1 int,
#Reps_1 int,
#ExerciseType_2 varchar(30),
#Equipment_2 varchar(30),
#Sets_2 int,
#Reps_2 int,
#ExerciseType_3 varchar(30),
#Equipment_3 varchar(30),
#Sets_3 int,
#Reps_3 int,
#ExerciseType_4 varchar(30),
#Equipment_4 varchar(30),
#Sets_4 int,
#Reps_4 int,
#WorkoutID int = SCOPE_IDENTITY
)
AS
SET xact_abort ON
BEGIN
INSERT INTO Program (MemberNumber, TrainerID, ProgramStartDate, TrainerReviewDate, Active)
VALUES (#MemberNumber, #TrainerID, #ProgramStartDate, #TrainerReviewDate, #Active);
INSERT INTO Workouts (Description, Day, ProgramID)
VALUES (#Description, #Day, SCOPE_IDENTITY());
INSERT INTO Exercise (ExerciseType, Equipment, Sets, Reps, WorkoutID)
VALUES (#ExerciseType_1, #Equipment_1, #Sets_1, #Reps_1, SCOPE_IDENTITY()),
(#ExerciseType_2, #Equipment_2, #Sets_2, #Reps_2, SCOPE_IDENTITY()),
(#ExerciseType_3, #Equipment_3, #Sets_3, #Reps_3, SCOPE_IDENTITY()),
(#ExerciseType_4, #Equipment_4, #Sets_4, #Reps_4, SCOPE_IDENTITY())
END;
GO
/*Test for usp_New_Program_4
Result: Failed - Error converting data type varchar to int*/
Exec usp_New_Program_4 21,3,'2020-06-06','2020-07-07','Y','Chest & Arms',SCOPE_IDENTITY,'Bench
Press','50kg Barbell',3,6,'Press Ups','Floor Mat',3,15,'Bicep Curls','15kg
Dumbells',3,6,'Tricep Extensions','15kg Dumbells',3,6,SCOPE_IDENTITY
Go
It looks like you may have missed a field in your line to execute the stored procedure. I quickly copied the stored proc input values into a spreadsheet followed by the values in your test line that throws the error. Have a look, it looks like you're missing perhaps the Day value? After that is entered it should line everything up correctly. I marked up the first line that after a quick glance looks like it is causing the error (others lower will too though, until the missing value is fixed).
Basic debugging would be to check your parameters... And if we do that...
Exec usp_New_Program_4 21, --#MemberNumber int
3, --#TrainerID int
'2020-06-06', --#ProgramStartDate date
'2020-07-07', --#TrainerReviewDate date
'Y', --#Active char(1)
'Chest & Arms', --#Description varchar(50)
SCOPE_IDENTITY, --#Day varchar(10)
'Bench
Press', --#ProgramID int
'50kg Barbell', --#ExerciseType_1 varchar(30)
3, --#Equipment_1 varchar(30)
6, --#Sets_1 int
'Press Ups', --#Reps_1 int
'Floor Mat', --#ExerciseType_2 varchar(30)
3, --#Equipment_2 varchar(30)
15, --#Sets_2 int
'Bicep Curls', --#Reps_2 int
'15kg
Dumbells', --#ExerciseType_3 varchar(30)
3, --#Equipment_3 varchar(30)
6, --#Sets_3 int
'Tricep Extensions', --#Reps_3 int
'15kg Dumbells', --#ExerciseType_4 varchar(30)
3, --#Equipment_4 varchar(30)
6, --#Sets_4 int
SCOPE_IDENTITY --#Reps_4 int
Pretty clear now. The value 'Bench
Press' is not an int. Neither are 'Press Ups'
, 'Bicep Curls' or 'Tricep Extensions'.
This is why using the format EXEC PROC {Proc Name} #{Parameter Name} = {Parameter Value} is really important for any procedures that have more than 1 or 2 parameters; you don't make simple mistakes like missing a parameter out.
In this case, you clearly missed out a value for #Day (as I assume you wanted to pass SCOPE_IDENTITY for #ProgramID), and thus all your parameters after that are wrong. The SP still ran fine though, as your last parameter (#WorkoutID) has a default value, and so didn't "mind" being omitted.

Yes/No column in SQL 2018 studio

Can anyone explain how to create a yes/no column in SQL Studio 2018? BOOL or bit(1) are not working.
Create Table Diseases
(
P_ID int not null,
NameofDis varchar(100),
DateofDis date,
Condition bit(1),
);
You can use simple BIT datatype or you can use BOOLEAN data type like this
Create Table Diseases(
P_ID int not null,
NameofDis varchar(100),
DateofDis date,
Condition BIT,
);
or
Create Table Diseases(
P_ID int not null,
NameofDis varchar(100),
DateofDis date,
Condition BOOLEAN,
);
Try using BIT instead of BIT(1). This will create the column as a yes/no field aka true/false field where 1 is yes/true and 0 is no/false.
Your code:
Create Table Diseases(
P_ID int not null,
NameofDis varchar(100),
DateofDis date,
Condition bit
);

Inserting record from one column to another column in the same scope or statement

I have a Stored Procedure that populates a table: This table as indicated in the code below has an identity column which is also the primary key column.
I would like to append the primary key to contain leading letters: Example: ABC123.
Obviously this is not possible because the Primary key column is INT datatype.
So I created an additional column so that I can insert the appended primary key. This works except I have to make the new column Null and I am using an UPDATE statement.
Something tells me there is a better way.
Is there a way I can do this without using UPDATE after the initial Insert and have the new column CategoryID as Not Null?
Table Code:
CREATE TABLE [dbo].[Registration] (
[SystemID] INT IDENTITY (100035891, 1) NOT NULL,
[CategoryID] CHAR (13) NULL,
[FName] VARCHAR (30) NOT NULL,
[LName] VARCHAR (30) NOT NULL,
[MInit] CHAR (1) NULL,
PRIMARY KEY CLUSTERED ([SystemID] ASC)
);
Stored Procedure:
CREATE PROCEDURE [dbo].[uspInsertRegistration]
#FName VARCHAR(30),
#LName VARCHAR(30),
#MInit CHAR(1),
#CategoryID CHAR(13),
#SystemID int OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #ErrCode int
INSERT INTO [dbo].[Registration] ([FName],[LName],[MInit])
VALUES (#FName, #LName, #MInit)
SELECT #ErrCode = ##ERROR, #SystemID = SCOPE_IDENTITY()
UPDATE [dbo].[Registration]
SET CategoryID = 'ABC'+ CAST(SystemID AS CHAR)
SET NOCOUNT OFF
RETURN #ErrCode
END
Finally this is what the table looks like with the data:
Thanks for being contagious with your knowledge. :)
Guy
My suggestion is to use a computed column, as what you're trying to do introduces redundancy. See below:
http://msdn.microsoft.com/en-us/library/ms191250%28v=sql.105%29.aspx
Alternately, make it big enough to contain a GUID, put a GUID into the column on the insert, then update it afterwards.

Altering SQL table to add column

I currently have a table with four columns - i wanted to add a fifth column but having some trouble.
I open the table in sql server studio management 2008 and i added the column info like so:
CREATE TABLE [dbo].[Case]
(
CaseId UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
CaseNumber NVARCHAR(50) NOT NULL,
CourtId INT NOT NULL,
DateOpened DATETIME NOT NULL,
)
my addition:
CREATE TABLE [dbo].[Case]
(
CaseId UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
CaseNumber NVARCHAR(50) NOT NULL,
CaseName NVARCHAR(50),
CourtId INT NOT NULL,
DateOpened DATETIME NOT NULL,
)
After adding CaseName column, i tried executing the table in Management Studio but i got the error message "There is already an object named 'Case' in the database."
I tried saving and then building my database hoping that the column will be added but that wasn't successful. I tried a New Query and writing the 'Alter table "case" add CaseName nvarchar(50) but again without luck. It shows that the file is changed with the new column because i saved it but after building my overall database it isn't making any changes. Any helpful tips will be great.
You want to ALTER, as follows:
ALTER TABLE [dbo].[Case] ADD CaseName NVARCHAR(50)
Better yet, you can check for the existance of the column first:
if not exists (SELECT 1 FROM sysobjects INNER JOIN syscolumns ON
sysobjects.id = syscolumns.id
WHERE sysobjects.name = N'Case' AND syscolumns.name = N'CaseName')
ALTER TABLE [dbo].[Case] ADD CaseName NVARCHAR(50)
you should try this
ALTER TABLE [dbo].[Case]
ADD CaseName NVARCHAR(50)
You are trying to create another table Case but one already exists that's why you have an error. When you want to edit a table, you have to use Alter table
Use an Alter table statement instead of Create
If you can't get the Alter statement to work for some reason, you could also drop the existing table and create a new one with the new field, but all your existing rows will be lost.
If you're using SSMS, you can Design the table instead of Edit to add the column.
ALTER is what you need to investigate (F1)
An alternative is.
Create a new table
CREATE TABLE [dbo].[Case2]
(
CaseId UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
CaseNumber NVARCHAR(50) NOT NULL,
CourtId INT NOT NULL,
DateOpened DATETIME NOT NULL,
newcolumn INT NULL
)
Move data from existing table into the new one
INSERT INTO [dbo].[Case2]
SELECT * FROM [dbo].[Case]
Then
DROP TABLE [dbo].[Case]
Then in management studio right-click 'Case2' and re-name it 'Case'
I recommend checking for the existence of the column prior to adding it, especially important when you work with migration scripts.
Here is how I usually do it:
IF NOT EXISTS(SELECT * FROM sys.columns WHERE Name = N'ColumnName' AND Object_ID = Object_ID(N'TableName'))
BEGIN
ALTER TABLE [dbo].TableName ADD ColumnName NVARCHAR(512) null
END

Storing metadata about a row with a database row?

What are the best practices regarding storing metadata about a row with a row?
Take the example of a inter-bank financial transfer. The Transfer might look like:
CREATE TABLE Transfers (
TransferID int,
FromTransit varchar(10),
FromBranch varchar(10),
FromAccount varchar(50),
ToTransit varchar(10),
ToBranch varchar(10),
ToAccount varchar(50),
Amount money,
Status varchar(50));
But now, of course, people will want to see meta-data:
ALTER TABLE Transfers
ADD
CreatedDate datetime,
LastModifiedDate datetime,
CreatedByUsername varchar(50),
CreatedByFullname varchar(200),
CreatedByWorkstation varchar(50),
VoidedDate datetime NULL,
VoidedByUsername datetime NULL,
VoidedByFullname datetime NULL,
VoidApprovedBySupervisorUsername varchar(50) NULL,
VoidApprovedBySupervisorFullname varchar(200) NULL,
VoidApprovedBySupervisorWorkstation varchar(50) NULL,
SentDate datetime NULL,
SentByUsername varchar(50) NULL,
SentByFullname varchar(50) NULL,
SentByWorkstation varchar(50) NULL,
SendApprovedBySupervisorUsername varchar(50) NULL,
SendApprovedBySupervisorFullname varchar(50) NULL,
SendApprovedBySupervisorWorkstation varchar(50) NULL,
SendConfirmationNumber varchar(50) NULL,
SentToRemoteMachineName varchar(50) NULL,
ReceivedDate datetime NULL,
ReceivedConfirmationNumber varchar(50) NULL,
ReceivedToRemoteMachineName varchar(50) NULL,
ReceivedByUsername varchar(50) NULL,
ReceivedByFullname varchar(50) NULL,
ReceivedByWorkstation varchar(50) NULL,
ReceiveApprovedBySupervisorUsername varchar(50) NULL,
ReceiveApprovedBySupervisorFullname varchar(50) NULL,
ReceivedApprovedBySupervisorWorkstation varchar(50) NULL,
ReceivedCheckedBySupervisorUsername varchar(50) NULL,
ReceivedCheckedBySupervisorFullname varchar(50) NULL,
ReceivedCheckedBySupervisorWorkstation varchar(50) NULL
)
These are all well-defined values, that will all appear on the hard-copy related to a transfer.
We already have audit logging of changes in tables, but that wouldn't catch something like:
UPDATE Transfers SET Status = 'TransferStatus_Received'
WHERE TransferID = 6744891
It would catch the username, fullname, and machine name of the person who made the change; but it can't know the name of the supervisor who was over the person's shoulder to enter their credentials to "authorize" the transfer to be received.
My aggravation comes when they ask for another piece of information to be tracked, and I have to add more metadata columns to my data table.
Is this best practice?
This is not good practice for financial databases because you allow updates. If you allow updates it does not matter what logging, auditing, crypto keys or whatever you add since a hostile party could just update them.
Instead you must forbid updates; all changes must be inserts. All tables should have an indexed sequential FK column and all joins are on Max(seq). This means you perform all transactions on the latest data but have a permanent record of every transaction on these tables.
Edit: If what you're asking is whether you should add the audit columns to the original table, that depends if the audit columns are sparse or nullable. From your comments, it seems they are.
In that case, you should create separate tables for each nullable group of audit attributes and perform an outer join on those tables, joining with the sequential column of the original database. This means you can add or drop audit tables at will without affecting your data table. Something like:
SELECT t.transferID, t.money, u.Date, u.workstation, s.name, ...
FROM Transfers t
LEFT OUTER JOIN Users u ON u.seq = t.seq
LEFT OUTER JOIN Supervisors s ON s.seq = t.seq
WHERE t.seq = (SELECT Max(seq) FROM Transfers WHERE whatever)
You can create a view or stored procedure that saves Max(seq) if you need to reuse it in a transaction.
I don't know much about SQL Server but when confronted with such in an Oracle scenario I tend to employ triggers (insert/update/delete) which take the complete row (before and after) into an "archive/audit" table and add whatever "metadata" they want logged along with it... this way my app-centric data model won't get poluted regarding applications/SPs etc. and no app/user has access to that sensitive logging/auditing information...