Getting an "Invalid object name" error in ADS after creating a new table - sql-server

I'm working on a new Jupyter Notebook, using SQL as the Kernel, to create a new table, populate it with a couple records, etc., then drop the table. I've written the CREATE TABLE DDL, then ran it. However, when I ran it in ADS it gave me an error on the table name ("Invalid object name ") and each column in the new table ("Invalid column name "). But it created the table, nonetheless. Huh? What's going on?
I've looked for similar questions posted here on SO, but none of the match my situation. For example, one of them the user had created the table as one name, but then tried to do a SELECT against a different table name, that was slightly different from the one they created. That's not the case for me. Here's the SQL DDL for creating the table:
IF OBJECT_ID('[dbo].[Bozo]', 'U') IS NOT NULL
DROP TABLE [dbo].[Bozo]
GO
-- Create the table in the specified schema
CREATE TABLE [dbo].[Bozo]
(
[Id] INT NOT NULL PRIMARY KEY, -- Primary Key column
[FirstName] NVARCHAR(50) NOT NULL,
[LastName] NVARCHAR(50) NOT NULL,
-- Specify more columns here
Bool1 BIT DEFAULT 1,
Bool2 BIT DEFAULT 1,
BoolValue AS Bool1 & Bool2
);
GO
And here's my SQL INSERT statements:
NSERT INTO Bozo (FirstName, LastName)
VALUES ('George', 'Washington');
INSERT INTO Bozo (FirstName, LastName, Bool2)
VALUES ('John', 'Adams', 0);

I discovered that the SQL Script that Azure Data Studio uses to create a new table does not define the Id column as an IDENTITY column. Changing that fixed the issue, so now it is:
IF OBJECT_ID('[dbo].[Bozo]', 'U') IS NOT NULL
DROP TABLE [dbo].[Bozo]
GO
-- Create the table in the specified schema
CREATE TABLE [dbo].[Bozo]
(
[Id] INT IDENTITY(1,1) NOT NULL PRIMARY KEY, -- Primary Key column
[FirstName] NVARCHAR(50) NOT NULL,
[LastName] NVARCHAR(50) NOT NULL,
-- Specify more columns here
Bool1 BIT DEFAULT 1,
Bool2 BIT DEFAULT 1,
BoolValue AS Bool1 & Bool2
);
GO

Related

On my local machine, I am unable to drop a table because it doesn't exist or I don't have permission

I am going through college and I'm doing an database class where we're introduced to the SQL Server Management Studio, so I'm very new to all of this. That being said, I've been following along and keeping up, making sure to note his queries... However, I noticed something. In the queries I've been making while keeping notes of my class, I have the error "cannot drop table because it does not exist or you don't have permissions".
Now this is odd to me, as I am the only user of this laptop, I am basically the administrator, I've created the database and tables as per instructions and yet, this issue is popping up and I'm unable to run my queries to see how they work.
Here's a snippet of my code, though I'm not sure how much it'd help...
-- Dropping tables in case they already exist
drop table Movie
drop table Genre
drop table Theater
drop table MovieTheater
-- Create table
create table Movie
(
MovieID int not null constraint PK_Movie primary key,
Title varchar(200) not null,
Budget money null,
ReleaseDate date null,
GenreCode char(1) not null constraint FK_MovieToGenre references Genre(GenreCode),
Released bit not null,
MovieLength decimal(5,2) null
)
create table Genre
(
GenreCode char(1) not null constraint PK_Genre primary key,
GenreDescription varchar(30) not null
)
create table Theater
(
TheaterID int not null constraint PK_Theater primary key,
TheaterName varchar(100) not null,
Address varchar(50) not null,
City varchar(50) not null,
Province char(2) not null,
PostalCode char(7) not null,
PhoneNumber char(13) not null
)
create table MovieTheater
(
MovieID int not null,
TheaterID int not null,
StartDate date not null,
EndDate date null,
constraint PK_MovieTheater primary key (MovieID, TheaterID)
)
I attempted changing the permissions of the database but it wouldn't allow me. Other solutions I've looked up all assume that it's connecting to a database for other purposes (likely work related)
The error is pretty clear. cannot drop table because it does not exist. You can't DROP a table that doesn't exist, just as you can't CREATE a table that already exists.
In SQL Server 2016 and later you can use DROP TABLE IF EXISTS to drop a table if it exists. Since the oldest version in mainstream support is SQL Server 2019, you can reasonably expect that IF EXISTS will work on any new database
DROP TABLE IF EXISTS [dbo].[MyTable0];
In older, now unsupported, versions you had to check explicitly in an IF :
IF OBJECT_ID(N'dbo.MyTable0', N'U') IS NOT NULL
DROP TABLE [dbo].[MyTable0];
The SQL Server DROP TABLE IF EXISTS Examples shows all these options. Use DROP TABLE IF EXISTS unless you really need to work with an unsupported database version.
From your code, I think the problem is you tried to drop the tables before you created them
-- Dropping tables in case they already exist
drop table Movie
drop table Genre
drop table Theater
drop table MovieTheater
To drop the table if only it has already exist, you could try:
IF OBJECT_ID('tableName', 'U') IS NOT NULL
DROP TABLE tableName;
Explain:
The OBJECT_ID function returns the object ID of the specified table. If the table does not exist, it returns NULL. The 'U' parameter indicates that we are looking for a user-defined table.
The IF statement checks whether the table exists by checking the result of the OBJECT_ID function. Simple as that!

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.

Cannot insert explicit value for identity column

I am migrating my application form one database to other with keeping table structure as it is. I am creating same tables in new table and inserted value using db link.
I am getting error message like "Cannot insert explicit value for identity column in table 'XYZ' when IDENTITY_INSERT is set to OFF." because table XYZ have ScreenConfigSettingAccessId as an identity column
Below is the script I am using for creating table and inserting value
CREATE TABLE [dbo].[XYZ](
[ScreenConfigSettingAccessId] [int] IDENTITY(1,1) NOT NULL,
[APP_ID] [int] NOT NULL,
[ScreenConfigSettingId] [int] NOT NULL,
[RSRC_ID] [char](20) NOT NULL)
)
INSERT INTO [dbo].[XYX]
(
[ScreenConfigSettingAccessId] ,
[APP_ID] ,
[ScreenConfigSettingId] ,
[RSRC_ID]
)
SELECT
[ScreenConfigSettingAccessId] ,
[APP_ID] ,
[ScreenConfigSettingId] ,
[RSRC_ID]
FROM [olddatabase].[database name].[dbo].[XYX]
in old table the value of ScreenConfigSettingAccessId is 3 and 4.
I want to inset the same data which old table have so set IDENTITY_INSERT to ON and tried but it still not allowing to insert.
Looking for you suggestions
You need to specify the table. Check out the command syntax in SQL Books Online: SQL 2000 or SQL 2012 (the syntax hasn't changed).

How to set "auto insert" foreign key value by using SQL Server?

I have created two tables and also created a relationship between them.
Table students:
create table students
(
[StudentId] NVARCHAR(50) NOT NULL PRIMARY KEY,
[Name] NVARCHAR(50) NOT NULL
);
Table studentprofile:
create table studentprofile
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY(1, 1),
[StudentId] NVARCHAR(50) NOT NULL,
[Address] NVARCHAR(50) NOT NULL,
);
and relationship:
alter table studentprofile
add constraint students_studentprofile_FK
foreign key (StudentId)
references students(StudentId)
on delete cascade on update cascade
But, when I wrote this line:
insert into students values('110111', 'Marik')
the value of StudentId (in table studentprofile) wasn't updated automatically. Why?
Can you tell me how to set the value of StudentId (in table studentprofile) can be inserted automatically whenever I insert into table students?
There is no such thing as insert cascade.
You can implement such a thing by using a trigger for insert on your students table, inserting default values (or nulls) into the studentprofile table:
CREATE TRIGGER students_insert ON students AFTER INSERT
AS
INSERT INTO studentprofile(StudentId, Address)
SELECT StudentId, 'NO ADDRESS'
FROM inserted
Note that your Address column is defined as not null and has no default value, this is why I've used the hard coded 'NO ADDRESS' for it.
However, I agree with the comments on your question: you would be better off inserting the data to the student profile using a different insert statement (perhaps inside a transaction with the insert to students).

Load user extract with stored procedure

I have a ASP MVC web application that is required to load a user extract each day from a file. The users in the database should be updated accordingly: deleted if not in source, updated if in source and target, and created if only in source. While doing this, certain rights should also automatically be given to the users. If there is any error, nothing should happen at all.
First I tried to do this with Entity Framework, but the SaveChanges call takes around two minutes to return, which is a lot for the relatively small amount of users (~140 000).
My idea now is to write a stored procedure that would do the updating. I would pass the list of new users as a parameter. The type of my temporary table:
CREATE TYPE [dbo].[TempUserType] AS TABLE
(
[Uid] NVARCHAR(80) NOT NULL PRIMARY KEY,
[GivenName] NVARCHAR(80) NOT NULL,
[FamilyName] NVARCHAR(80) NOT NULL,
[Email] NVARCHAR(256) NOT NULL,
[GiveRight1] BIT NOT NULL,
[GiveRight2] BIT NOT NULL,
[GiveRight3] BIT NOT NULL
)
The users:
CREATE TABLE [dbo].[User] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Uid] NVARCHAR (80) NOT NULL,
[GivenName] NVARCHAR (80) NOT NULL,
[FamilyName] NVARCHAR (80) NOT NULL,
[Email] NVARCHAR (256) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
UNIQUE NONCLUSTERED ([Uid] ASC)
);
The user roles:
CREATE TABLE [dbo].[UserRole] (
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [FK_UserRole_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([Id]),
CONSTRAINT [FK_UserRole_Role] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[Role] ([Id])
);
The procedure I am stuck writing:
CREATE PROCEDURE [dbo].[UpdateUsers]
#extractedUsers TempUserType READONLY
AS
BEGIN TRANSACTION
MERGE
[dbo].[User] AS trg
USING
#extractedUsers AS src
ON
(trg.[Uid] = src.[Uid])
WHEN MATCHED THEN
UPDATE SET
trg.GivenName = src.GivenName,
trg.FamilyName = src.FamilyName,
trg.Email = src.Email
WHEN NOT MATCHED BY TARGET THEN
INSERT
([Uid], GivenName, FamilyName, Email)
VALUES
(src.[Uid], src.GivenName, src.FamilyName, src.Email)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
COMMIT TRANSACTION
My question: is the use of a procedure with merge appropriate in this case to achieve the performance improvement over EF? How can I attribute roles according to the 3 boolean values that are in the source table?
Roles can be hadcoded, meaning I know that the Right1 corresponds to the RoleId 1, Right 2 to RoleId 2 and Right 3 to RoleId3.
After reading the question I want to leave an idea for the solution.
For me it makes more sense to have an IF / ELSE for calling the update or the insert, not using the merge since you need the UserId that you are updating/inserting to add it's role permissions.
You can check if UId exists and if so update the user details, if does not exists then create and keep the new Identity value.
In both cases, when having the user ID add the corresponding permissions according to the boolean values with IF statements.
Pseudo-code:
If UserId exists in UsersTable
Update
Store UserId
Else
Insert
Store created UserId (using the ##IDENTITY)
If bool1 add permission 1
If bool3 add permission 2
If bool3 add permission 3

Resources