Adding Columns to Multiple Tables in SQL - sql

I just created a database and then added a couple of hundred tables with a script like this:
CREATE TABLE CapBond
(
[timestamp] varchar(50),
[Reward] varchar(50),
[Award] varchar(50),
[Fact] varchar(50)
)
CREATE TABLE Values
(
[timestamp] varchar(50),
[Name] varchar(50),
[Test] varchar(50),
[Read] varchar(50),
[Parameters] varchar(50)
)
I realize I forgot to add two columns to each table. One for the PK and one for an FK that points back to a 'master' table.
Is there an easy way to insert columns without having to drop the DB and recreate it? Preferably with the columns inserted as the first two columns in the table?

Yes. In mysql you have the alter table command for this purpose. Check out this page for more detailed explanation
https://www.sqlservertutorial.net/sql-server-basics/sql-server-alter-table-add-column/ .
And here is the solution for the ordering of the columns
https://www.mysqltutorial.org/mysql-add-column/

Related

Order of rows changes when creating table

I've a weird issue.
DROP table IF EXISTS ipl;
CREATE TABLE ipl(
match_id VARCHAR(50),
batting VARCHAR(50),
bowling VARCHAR(50),
overn VARCHAR(50),
batsman VARCHAR(50),
bowler VARCHAR(50),
super_over VARCHAR(50),
bat_runs VARCHAR(50),
extra_runs VARCHAR(50),
total_runs VARCHAR(50),
player_out VARCHAR(50),
how VARCHAR(50),
fielder VARCHAR(50));
BULK INSERT ipl
FROM 'F:\Study\Semesters\4th
Sem\COL362\HomeWork\1\Dataset\deliveries.csv'
WITH(FIELDTERMINATOR= ',');
SELECT * FROM ipl;
This is the code I'm using to make the table in SSMS. match_id goes from 1 to about 290, in increasing order in the csv file. When I executed this query once, everything was ok. But, when I did that again, some rows from the middle were moved to the last.
You can see that below:
(Note that jump from 4 to 49)
I don't know what's wrong. Please help me resolve this issue. Thanks!
SQL tables represent unordered sets. If you want rows in a particular order, you need an order by. How can you do this with a bulk insert? Well, you need an identity column. The idea is to create the table with an identity and use a view for the bulk insert:
create table ipl (
ipl_id int identity(1, 1) primary key,
. . .
);
create view vw_ipl as
select match_id, batting, bowling, . . .
from ipl
bulk insert vw_ipl
from 'F:\Study\Semesters\4th Sem\COL362\HomeWork\1\Dataset\deliveries.csv'
with (fieldterminator= ',' );
select *
from ipl
order by ipl_id;
As a relational database SQL server do not guarantee a particular order of returned data. If you need ordered data, specify order by clause.

Creating table when each object may have a list of values

First I've created a table with information on stores and transactions with the following query:
CREATE TABLE main.store_transactions
(
store_id varchar(100) NOT NULL,
store_name varchar(100),
store_transaction_id varchar(100),
transaction_name varchar(100),
transaction_date timestamp,
transaction_info varchar(200),
primary_key(store_id)
)
But then I realized that the same store may have various transactions related to it, not just one. How should I implement table creation in this case?
One thing that comes to mind is to create a separate table with transactions, each transaction having store_id as a foreign key. And then just join when needed.
How is it possible to implement it in a single table?
Well, the most elegant way would be indeed to create a satelite table for your stores and reference it to the store_transactions table, e.g:
CREATE TABLE stores
(
store_id varchar(100) NOT NULL PRIMARY KEY,
store_name varchar(100)
);
CREATE TABLE store_transactions
(
store_id varchar(100) NOT NULL REFERENCES stores(store_id),
store_transaction_id varchar(100),
transaction_name varchar(100),
transaction_date timestamp,
transaction_info varchar(200)
);
With this structure you will have many transactions to a single store.
There are other less appealing options, such as customizing a data type for stores and creating an array of it in the table store_transactions. But regarding the costly maintainability of such approach, I would definitely discourage it.

Derived table with an index

Please see the TSQL below:
DECLARE #TestTable table (reference int identity,
TestField varchar(10),
primary key (reference))
INSERT INTO #TestTable VALUES ('Ian')
select * from #TestTable as TestTable
INNER JOIN LiveTable on LiveTable.Reference=TestTable.Reference
Is it possible to create an index on #Test.TestField? The following webpage suggests it is not. However, I read on another webpage that it is possible.
I know I could create a physical table instead (for #TestTable). However, I want to see if I can do this with a derived table first.
You can create an index on a table variable as described in the top voted answer on this question:
SQL Server : Creating an index on a table variable
Sample syntax from that post:
DECLARE #TEMPTABLE TABLE (
[ID] [INT] NOT NULL PRIMARY KEY,
[Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL,
UNIQUE NONCLUSTERED ([Name], [ID])
)
Alternately, you may want to consider using a temp table, which will persist during the scope of the current operation, i.e. during execution of a stored procedure exactly like table variables. Temp tables will be structured and optimized just like regular tables, but they will be stored in tempDb, therefore they can be indexed in the same way as regular table.
Temp tables will generally offer better performance than table variables, but it's worth testing with your dataset.
More in depth details can be found here:
When should I use a table variable vs temporary table in sql server?
You can see a sample of creating a temp table with an index from:
SQL Server Planet - Create Index on Temp Table
One of the most valuable assets of a temp table (#temp) is the ability
to add either a clustered or non clustered index. Additionally, #temp
tables allow for the auto-generated statistics to be created against
them. This can help the optimizer when determining cardinality. Below
is an example of creating both a clustered and non-clustered index on
a temp table.
Sample code from site:
CREATE TABLE #Users
(
ID INT IDENTITY(1,1),
UserID INT,
UserName VARCHAR(50)
)
INSERT INTO #Users
(
UserID,
UserName
)
SELECT
UserID = u.UserID
,UserName = u.UserName
FROM dbo.Users u
CREATE CLUSTERED INDEX IDX_C_Users_UserID ON #Users(UserID)
CREATE INDEX IDX_Users_UserName ON #Users(UserName)

Type collection in a table SQL Server Compact

I work on a program VB.Net using a SQL Server Compact database.
I want to create a table PRODUCTION where I can have many employees so I want to create a column as collection of names of employees:
This is the table Employee :
CREATE TABLE [Employee]
(
[ID] INT NOT NULL IDENTITY (1,1),
[nom] NVARCHAR(100),
[salaire] REAL,
[date_debut] DATETIME,
[tache] NVARCHAR(100)
);
ALTER TABLE [Employe] ADD CONSTRAINT [PK_Employe] PRIMARY KEY ([ID]);
The table PRODUCTION I want to create :
create table production(
ID int not null identity(1,1),
date_prod Datetime,
emp collection (emp1,emp2, ...));
Explanation: in the table Production, I will have many employees, so I want to insert them in one line of the entry.
Any idea?

SQL Server 2008 stored procedure for a table having two foreign keys and both of them is a composite key

I have the following tables :
create table ApartmentInfo(
ApartmentId int primary key identity,
ApName nvarchar(50))
create table [User](
UserId int primary key identity,
FirstName nvarchar(50),
LastName nvarchar(50),
Username nvarchar(50),
[Password] nvarchar(50),
[Description] nvarchar(200))
create table ApUser(
ApartmentId int foreign key references ApartmentInfo(ApartmentId),
UserId int foreign key references [User](UserId),
primary key(ApartmentId,UserId))
Summary of the usage is: suppose I have 10 apartments in my Apartmentinfo table and 3 users in the [User] table.
Now I want to write a stored procedure such that:
every UserId has all 10 ApartmentId's, and whenever a new apartment is created in ApartmentInfo table it will also be added in ApUser table again having all 3 userId's.
And if a new user is created in User table then it will also have all the 10 ApartmentId's related with it in ApUser table.
Thanks in advance, I am new to SQL Server and I don't know how it can be done or not but, if it is possible then please let me know, I will be grateful to you, thanks.
If you're not dead set on using a stored procedure this use case seems like an excellent fit for server side triggers:
IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[trigger_insert_apartment]'))
DROP TRIGGER [dbo].[trigger_insert_apartment]
GO
CREATE TRIGGER trigger_insert_apartment
ON ApartmentInfo FOR INSERT
AS INSERT ApUser(ApartmentId, UserId ) SELECT i.ApartmentId, u.UserId FROM [User] AS u, inserted AS i
GO
IF EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[trigger_insert_user]'))
DROP TRIGGER [dbo].[trigger_insert_user]
GO
CREATE TRIGGER trigger_insert_user
ON [User] FOR INSERT
AS INSERT ApUser(ApartmentId,UserId ) SELECT a.ApartmentId, i.UserId FROM ApartmentInfo AS a, inserted AS i
GO
These two triggers will insert all apartments or users into the apinfo table when you add a new user or apartment, and if I understood your question that was what you wanted?
To address your question about what you'd do to associate apartments with users IF YOU WANTED TO LATER...
If you're restricting which apartments a user has access to view, I would NOT associate them individually to every user. BUT, if they're manually adding a "watch" on an apartment in your application, then this is ok to do. If you want to only show them a certain set of apartments, try to group them in a logical way if you can. So maybe have an ApartmentGroup lookup table:
ApartmentGroup(ApartmentGroupId (Int), ApartmentGroupName varchar(50))
and assign an ApartmentGroupId to each apartment. Then you can have a join table for ApUser and ApartmentGroup. That way you're not associating every apartment with every user.
However, if you want to add the apartment to each user still, then in your InsertApartment stored procedure, just insert it into the ApUser table as well.