What is the uniqueidentifier (default newid()) was inserted? - sql-server

I have a table with a uniqueidentifier and NEWID() default for new records. Executed the insert script. How do I know what uniqueidentifier was generated for the Id column since the last insert?
Table Script
CREATE TABLE [dbo].[MyData](
[Id] [uniqueidentifier] NOT NULL,
[Data] [varbinary](max) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyData] ADD CONSTRAINT [DF_MyData_Id] DEFAULT (newid()) FOR [Id]
GO
Insert Script
INSERT INTO dbo.MyData (Data)
VALUES (NULL)
GO
What is the uniqueidentifier was inserted?

Use an OUTPUT clause. I INSERT the data into a table variable so that is it can consumed by other statements afterwards:
DECLARE #IDs table (ID uniqueidentifier);
INSERT INTO dbo.MyData
OUTPUT inserted.Id
INTO #IDs
DEFAULT VALUES;
SELECT *
FROM #IDs;

There is no particular value in relying on the default in your example.
Just create a scalar variable of type uniqueidentifier and assign it the result of NEWID yourself
DECLARE #Id UNIQUEIDENTIFIER = NEWID();
INSERT INTO dbo.MyData (Id)
VALUES (#Id);
This is more concise than having to insert into a table variable and subsequently select from it.

Related

How to insert values into two SQL Server tables updating primary key and foreign key simultaneously, using a procedure?

I have something like this:
CREATE TABLE [dbo].[table1]
(
[id1] [int] IDENTITY(1,1) NOT NULL,
[data] [varchar](255) NOT NULL,
CONSTRAINT [PK_table1] PRIMARY KEY(id1)
)
CREATE TABLE [dbo].[table2]
(
[id2] [int] IDENTITY(1,1) NOT NULL,
[id1] [int] ,
CONSTRAINT [PK_table2] PRIMARY KEY (id2)
CONSTRAINT [FK_table2] FOREIGN KEY(id1) REFERENCES Table1
)
I want to add values to both the tables using a procedure. I'm not adding any key values just data values.
If I use INSERT INTO to add data into Table 1, its primary key will be autoincremented. I will also be incrementing the Table 2 in the same procedure.
I want that the autoincremented primary key of Table 1 should automatically be updated as foreign key in Table 2 when I run that procedure.
You need to do something like this:
CREATE PROCEDURE dbo.InsertData (#data VARCHAR(255))
AS
BEGIN
-- Insert row into table1
INSERT INTO dbo.Table1 (data) VALUES (#data);
-- Capture the newly generated "Id1" value
DECLARE #NewId1 INT;
SELECT #NewId1 = SCOPE_IDENTITY();
-- Insert data into table2
INSERT INTO dbo.table2 (Id1) VALUES (#NewId1);
END
I don't know if I understand what do you want to do but I think you can do something like this:
INSERT INTO table1 (data) VALUES 'mydata'
DECLARE #LastKey INT
SET #LastKey = SCOPE_IDENTITY() -- FOR SQL SERVER, OR LAST_INSERT_ID() FOR MYSQL
INSERT INTO table2 (data) VALUES #LastKey

Stored Procedure: Unable to execute after creation

I have created a stored procedure which does four things:
create a table
Alter the created table with a new column
Update the new column based on a condition
Alter table again to drop a column.
I created the stored procedure but cannot execute. I get this error
Column name or number of supplied values does not match table definition'
I have checked all the columns and their datatype to ensure they match so I am at my wit's end as to where it has gone wrong. This is my first time writing a stored procedure, so it may be that my code structure is completely wrong. I have attached a simplified code here showing the basic structure and I am hoping if someone can have a look if the structure is right and shed some light!
Thanks a lot
Michelle
SET ANSI_NULLS ON
GO
CREATE PROCEDURE myStoredProcedure
AS
BEGIN
SET NOCOUNT ON
IF OBJECT_ID('newTable') IS NULL
BEGIN
CREATE TABLE newTable
(
[name] [nvarchar] (256) NOT NULL,
[id] [int] NOT NULL,
[date] [datetime2] (7) NULL
)
END;
TRUNCATE TABLE newTable;
INSERT INTO newTable
SELECT [name], [id], [date]
FROM table1;
ALTER TABLE newTable
ADD [Flag] [nvarchar](2) NULL;
UPDATE newTable
SET [Flag] = 1
WHERE YEAR([date]) = 2020;
ALTER TABLE newTable
DROP COLUMN [date];
END;
As per the Guru's comments above, rather create the table as it should be created originally, then update data in it accordingly with your SP.
I altered your SP to work, however, this is still not the correct way to actually use a SP.
See below altered SP:
SET ANSI_NULLS ON
GO
CREATE PROCEDURE myStoredProcedure
AS
BEGIN
SET NOCOUNT ON
IF OBJECT_ID('newTable') IS NULL
BEGIN
CREATE TABLE newTable
(
[id] int primary key identity,
[name] nvarchar(256) NOT NULL,
[date] datetime2 (7) NULL ,
[Flag] nvarchar(2) NULL
)
END;
INSERT INTO newTable (
[name],
[date]
)
SELECT
[name],
[date]
FROM table1;
UPDATE newTable
SET [Flag] = 1
WHERE YEAR([date]) = 2020;
END;
I removed the code to drop the Date Column as this is ill advised.

How to assign a permanent unique ID with T-SQL

Can someone let me know how to permanently assign a unique ID to a field?
I have the following table:
CREATE TABLE PrestigeCars.Reference.Staff
(
StaffName NVARCHAR(50) NULL,
ManagerID INT NULL,
Department NVARCHAR(50) NULL
) ON [PRIMARY]
GO
The following code assigns a new id field to to the table called 'myuniqueID'
SELECT
Staff.StaffName
,Staff.ManagerID
,Staff.Department
,NEWID() AS myuniqueID
FROM Reference.Staff
This will produce the following table:
The problem is I would like the unique IDs generated to become permanent.
Can someone let me know if that is possible?
CREATE TABLE PrestigeCars.Reference.Staff (
StaffName NVARCHAR(50) NULL
,ManagerID INT NULL
,Department NVARCHAR(50) NULL
, UniqueId NVARCHAR(255) NOT NULL default NEWID()
) ON [PRIMARY]
GO
Important is, that this only works for creating the table. If you want to alter the table, you firstly have to add the Column which has to allow null, then fill the values and at last set it to not null.
Edit:
To add a Column you need the alter table statement, as mentioned in many other posts before:
ALTER TABLE PrestigeCars.Reference.Staff
ADD UniqueId NVARCHAR(255) NULL default NEWID()
Next you have to set the UniqueId for the existing rows:
UPDATE PrestigeCars.Reference.Staff
SET UniqueId = NEWID()
WHERE UniqueId IS NULL
Last but not least you should set the column to not null:
ALTER TABLE PrestigeCars.Reference.Staff
ALTER COLUMN UniqueId NOT NULL
You could add an Unique-Index, if you want to, but this should not be necessary.

How to have an identity column for a temp table in SQL?

How to have an identity column for a temp table in SQL?
Explicit value must be specified for identity column in table '#T'
either when IDENTITY_INSERT is set to ON or when a replication user is
inserting into a NOT FOR REPLICATION identity column.
I am getting SQL Syntax error for the below block.
if object_id('tempdb.dbo.#t') is not null
drop table #t
create table #t
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[TotalCount] int,
[PercentageComplete] nvarchar(4000)
)
insert into #t
select totalcount, percentagecomplete from table_a
Add this to your query after table declaration
SET IDENTITY_INSERT #t OFF
This should fix it. The following code works on my machine
CREATE TABLE #t
(
[ID] [INT] IDENTITY(1,1) NOT NULL,
[TotalCount] INT,
[PercentageComplete] NVARCHAR(4000)
)
SET IDENTITY_INSERT #t OFF
INSERT INTO #t
SELECT
totalcount, percentagecomplete
FROM
table_a

How to automatically create rows and pass values to other tables

There are three tables in database:
"BusinessEntity " which has the identity column "BusinessEntityID" as Primary Key (as well as rowguid and ModifiedDate columns).
"Firm" which has similarly the identity column "BusinessEntityID" as Primary Key, which is also a Foreign Key to BusinessEntity.BusinessEntityID (it has a 1-to-1 relationship with "BusinessEntity" table, FirmName, rowguid and ModifiedDate columns ).
"Customer" which has the identity column "CustomerID" as Primary Key and column "FirmID" as Foreign Key to Firm .BusinessEntityID (plus CustomerName, rowguid and ModifiedDate columns).
i.e. (also see image)
tables: BusinessEntity Firm Customer
columns: CustomerID (PK)
BusinessEntityID(PK) --> BusinessEntityID (PK/FK) --> FirmID (FK)
What I'm trying to do is whenever a new Customer row is to be created:
A new BusinessEntity row to be created automatically and then pass its BusinessEntityID value to an (automatically) newly created Firm row which it turn would pass its own BusinessEntityID to Customer table as FirmID column.
As you can see a BusinessEntity row was no meaning unless it corresponds to a Firm (or other entities) and a Customer must include a Firm.
I created a view containing all three tables along with a trigger to do the job without success. Any suggestions?
The tables:
BusinessEntity
CREATE TABLE [dbo ].[BusinessEntity](
[BusinessEntityID] [int] IDENTITY(1,1) NOT NULL,
[rowguid] [uniqueidentifier] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_BusinessEntity_BusinessEntityID] PRIMARY KEY CLUSTERED
(
[BusinessEntityID] ASC
)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[BusinessEntity] ADD CONSTRAINT [DF_BusinessEntity_rowguid]
DEFAULT (newid()) FOR [rowguid]
GO
ALTER TABLE [dbo ].[BusinessEntity] ADD CONSTRAINT [DF_BusinessEntity_ModifiedDate]
DEFAULT (getdate()) FOR [ModifiedDate]
GO
Firm
CREATE TABLE [dbo].[Firm](
[BusinessEntityID] [int] IDENTITY(1,1) NOT NULL,
[FirmName] [nvarchar](30) NULL,
[rowguid] [uniqueidentifier] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Firm_BusinessEntityID] PRIMARY KEY CLUSTERED
(
[BusinessEntityID] ASC
)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Firm] ADD CONSTRAINT [DF_Firm_rowguid]
DEFAULT (newid()) FOR [rowguid]
GO
ALTER TABLE [dbo].[Firm] ADD CONSTRAINT [DF_Firm_ModifiedDate]
DEFAULT (getdate()) FOR [ModifiedDate]
GO
ALTER TABLE [dbo].[Firm] WITH CHECK ADD CONSTRAINT [FK_Firm_BusinessEntity_BusinessEntityID] FOREIGN KEY([BusinessEntityID])
REFERENCES [dbo].[BusinessEntity] ([BusinessEntityID])
GO
ALTER TABLE [dbo].[Firm] CHECK CONSTRAINT [FK_Firm_BusinessEntity_BusinessEntityID]
GO
Customer
CREATE TABLE [dbo].[Customer](
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[FirmID] [int] NULL,
[CustomerName] [nvarchar](28) NULL,
[rowguid] [uniqueidentifier] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Customer_CustomerID] PRIMARY KEY CLUSTERED
(
[CustomerID] ASC
)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT [DF_Customer_rowguid]
DEFAULT (newid()) FOR [rowguid]
GO
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT [DF_Customer_ModifiedDate]
DEFAULT (getdate()) FOR [ModifiedDate]
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [FK_Customer_Firm_FirmID] FOREIGN KEY([FirmID])
REFERENCES [dbo].[Firm] ([BusinessEntityID])
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [FK_Customer_Firm_FirmID]
GO
Something weird happens here. I created this stored procedure:
CREATE PROCEDURE [dbo].[CreateFirmCustomer](#FirmName NVARCHAR(30), #CustomerName NVARCHAR(28)) AS
BEGIN;
SET NOCOUNT ON;
BEGIN TRANSACTION;
INSERT BusinessEntity DEFAULT VALUES;
DECLARE #BusinessEntityID INT = SCOPE_IDENTITY();
SET IDENTITY_INSERT [dbo].[Firm] ON
INSERT Firm(BusinessEntityID, FirmName)
VALUES (#BusinessEntityID, #FirmName);
SET IDENTITY_INSERT [dbo].[Firm] OFF
INSERT Customer(FirmID, CustomerName)
VALUES (#BusinessEntityID, #CustomerName);
DECLARE #CustomerID INT = SCOPE_IDENTITY();
SELECT #BusinessEntityID AS FirmID, #CustomerID AS CustomerID;
COMMIT;
END;
GO
When I run it sometimes the CustomerID column gets the value of BusinessEntityID column when it should really be independently auto-generated. Also the BusinessEntityID column auto-generates weird values e.g. jumped from value 7 to value 1002. (BusinessEntityID is BusinessEntity.BusinessEntityID ) Any clues? (see picture)
Now I created this view to insert Customers as Firms:
CREATE VIEW [dbo].[vBusEntityFirmCustomer]
AS
SELECT dbo.Firm.FirmName, dbo.Customer.CustomerName
FROM dbo.BusinessEntity INNER JOIN
dbo.Firm ON dbo.BusinessEntity.BusinessEntityID = dbo.Firm.BusinessEntityID INNER JOIN
dbo.Customer ON dbo.Firm.BusinessEntityID = dbo.Customer.FirmID
GO
And this trigger on the view:
CREATE TRIGGER [dbo].[trg_FirmCustomer]
ON [dbo].[vBusEntityFirmCustomer]
INSTEAD OF INSERT
AS
exec [dbo].[CreateFirmCustomer]
GO
But every time I enter a new FirmName CustomerName to insert a new row I get this message (see image):
Procedure or function 'CreateFirmCustomer' expects parameter '#FirmName', which was not supplied.
The fact is that I do supply FirmName.
Logically, as designed, you have to create a BusinessEntity first, then a Firm, then a Customer. Across all these tables, the only real information you're storing is the firm name and the customer name -- all the rest is derived and autogenerated by the database. We can encapsulate the operation CreateCustomer in a stored procedure:
CREATE PROCEDURE CreateCustomer(#FirmName NVARCHAR(30), #CustomerName NVARCHAR(28)) AS
BEGIN;
SET NOCOUNT ON;
BEGIN TRANSACTION;
INSERT BusinessEntity DEFAULT VALUES;
DECLARE #BusinessEntityID INT = SCOPE_IDENTITY();
INSERT Firm(BusinessEntityID, FirmName)
VALUES (#BusinessEntityID, #FirmName);
INSERT Customer(FirmID, CustomerName)
VALUES (#BusinessEntityID, #CustomerName);
DECLARE #CustomerID INT = SCOPE_IDENTITY();
-- Return IDs of the newly created rows as the result set
SELECT #BusinessEntityID AS FirmID, #CustomerID AS CustomerID;
COMMIT;
END;
Invoke as (for example) EXEC CreateCustomer 'Firm', 'Customer'. With the table definitions as given, this will fail because Firm.BusinessEntityID is an IDENTITY -- if it is to take its value from BusinessEntity, it shouldn't be. (You can work around this with IDENTITY_INSERT, but in a properly designed database this shouldn't be necessary.)
Another thing that's obviously weird is that we insert no business data at all in BusinessEntity (which is why we need the DEFAULT VALUES syntax) -- it's nothing but a super-general container of IDs, so it's of dubious value. Nevertheless, this demonstrates the general technique of inserting rows in multiple tables that have dependencies.
As written, this stored procedure always creates a new Firm and BusinessEntity to go along with the Customer. Logically, a Firm can have more than one Customer, so you probably want another stored procedure to create a Customer for an existing Firm. This is simpler, as it's just an INSERT in Customer with the appropriate FirmID. You may wish to have a separate CreateFirm stored procedure that you call first, followed by a CreateCustomer to add a customer for that firm.
According to me,
it all depend how and when those 3 tables are populated.
Suppose those three table are populated using single UI, then
I will write them in single proc within one transaction.
Suppose those 3 table will be will populated at diff stage i.e diff UI then i write them in diff proc as you have already define constraint.
BTW what is the purpose of rowguid in all 3 tables.

Resources