GO
-- Create sproc for returning whether a partner has marked their survey as finished
CREATE PROCEDURE CheckIfFinished
#pid UNIQUEIDENTIFIER,
#sid INT
AS
BEGIN
SELECT COUNT(*) FROM Finished WHERE partner_id=#pid AND survey_id=#sid;
END
GO
gives
Invalid object name 'Finished'.
Same as if I changed Finished to MyDatabaseName.dbo.Finished or dbo.Finished.
Makes no sense.
The full context is
CREATE TABLE Finished (
partner_id UNIQUEIDENTIFIER,
survey_id INT,
PRIMARY KEY (partner_id,survey_id),
FOREIGN KEY (partner_id) REFERENCES Partners(id),
FOREIGN KEY (survey_id) REFERENCES Surveys(id)
);
GO
CREATE PROCEDURE CheckIfFinished
#pid UNIQUEIDENTIFIER,
#sid INT
AS
BEGIN
SELECT COUNT(*) FROM Finished WHERE partner_id=#pid AND survey_id=#sid;
END
GO
CREATE PROCEDURE UpdateFinishValue (#partner_id UNIQUEIDENTIFIER,
#survey_id INT,
#finished TINYINT)
AS
BEGIN
IF (#finished = 1 AND NOT EXISTS (SELECT 1
FROM Finished
WHERE Finished.partner_id=#partner_id AND Finished.survey_id=#survey_id))
INSERT INTO Finished (partner_id,survey_id) VALUES (#survey_id,#partner_id)
ELSE
DELETE FROM Finished WHERE partner_id=#partner_id AND survey_id=#survey_id
END
GO
The DBMS is unable to find this object period.
You can check for the table using this simple query:
select * from sys.sysobjects so
where so.name like N'%Finished%'
and so.xtype = N'U'
Also the most common causes to your problem are:
You are looking in the wrong place (server, DB, Schema...)
You lack permission to look for the object.
You got a case-sensitive collation issue.
The objects don't exists (maybe was not created or rolled back)
Related
I'm tring to upload data from python to a temp table in database and delete it after use. However, everytime I rerun it, it always gives a error
There is already an object named 'PK_temp' in the database.
It seems very strange to me as I think by dropping the temp table, the primary key I created for this table will also be dropped automatically.
To be more specific, I'm doing this
Step 1: drop the temp table if there is any
run_sql("""IF OBJECT_ID (N'tempdb..#temp') IS NOT NULL drop table #temp""", engine)
Step 2: create the temp table with a primary key and upload data by passing it as xml string
query = """
set nocount on;
declare #temp varchar(max);
select #temp = '{xml_str}';
-- CREATE TEMP TABLES
CREATE TABLE #temp(
id int not null,
CONSTRAINT PK_temp PRIMARY KEY (id asc),
);
-- EXTRACT XML INTO TEMP TABLES
declare #xml xml
declare #hdoc int;
select #xml = #temp
exec sp_xml_preparedocument #hdoc OUTPUT, #xml
insert into #temp (id)
select id
from OPENXML(#hdoc, '/data/row', 2)
with (id int)
exec sp_xml_removedocument #hdoc;
""".format(xml_str = id_xml_str)
run_sql(query, engine)
To be more clear, my run_sql looks like this
def run_sql(sql, engine)
session = Session(engine)
try:
session.execute(clause=sql)
session.commit()
except Exception as e:
session.rollback()
raise e
finally:
session.close()
return
and id_xml_str will be looks like this:
"
<data>\n
<row>\n <index>0</index>\n <id>18511</id>\n </row>\n
<row>\n <index>1</index>\n <id>18671</id>\n </row>\n
<row>\n <index>2</index>\n <id>18711</id>\n </row>\n
<row>\n <index>3</index>\n <id>18833</id>\n </row>\n
<row>\n <index>4</index>\n <id>18965</id>\n </row>\n
</data>"
I was wondering if some one can shed on some light on why this would happen and how to fix this?
BTW, I'm using
python==3.7
sqlalchemy==1.3.20
Just remove the PK name to give the PK a unique auto-generated name.
CREATE TABLE #temp
(
id int not null,
PRIMARY KEY (id asc),
);
Temporary tables have unique names generated for them in TempDb, but primary key constraints are separate objects, and you can't have two constraints with the same name in a single schema in any database.
So if two different sessions try to create a temp table with the same named constraint, one will fail.
I want to create a trigger which will check if my showtime with Cinema Hall Id exist or not. This will prevent me from booking one Cinema hall at two same Showtimes.
Secondly in this trigger I am also checking if the showtime I am assigning to movie lies in movie release and last date range or not.
But I don't know why none of the statement is working.
Create table Movie([Movie_ID] int primary key not null,[Movie_Name] varchar(50) Unique not null,[Realease_Date] date not Null,[Last_Date] date,Runtime time(0) not null ,Status varchar(20) not null,Rating float)
Create table [Showtime]([Showtime_ID] int primary key not null,Date date not null,Time time(0) not Null)
Create table [Cinema Halls]([Cinema_Halls_ID] int primary key not null,[Total_Seats] int not Null)
Create table [Movie Schedule] (
[Movie_Schedule_ID] int primary key not null,
[Movie_ID] int NOT null,
[Showtime_ID] int not null,
Cinema_Halls_ID int not null
Constraint fk_M_ID FOREIGN KEY ([Movie_ID]) REFERENCES Movie([Movie_ID]),
Constraint fk_Sh_ID FOREIGN KEY ([Showtime_ID]) REFERENCES Showtime([Showtime_ID]),
Constraint fk_C_ID FOREIGN KEY ([Cinema_Halls_ID]) REFERENCES [Cinema Halls] ([Cinema_Halls_ID])
)
/*Trigger Stops duplicate booking of Cinema halls and invalid showtime of movie*/
Create Trigger Trigger_Movie_Shedule
On "Movie Schedule"
After Insert,Update
As
declare #Cinema_Halls_ID int ,#Showtime_ID int,#Movie_ID int,#Release_Date Date,#Last_Date Date, #Showtime_Date date;
Select #Cinema_Halls_ID =Cinema_Halls_ID from inserted ;
Select #Showtime_ID=Showtime_ID from inserted;
Select #Movie_ID=Movie_ID from inserted;
Select Showtime_Date=Date from Showtime where Showtime_ID=#Showtime_ID
Select #Release_Date= Release_Date from Movie where Movie_ID=#Movie_ID;
Select #Last_Date=Last_Date from Movie where Movie_ID=#Movie_ID;
IF EXISTS (select count (Showtime_ID) from "Movie Schedule"
where Showtime_ID = #Showtime_ID and Cinema_Halls_ID = #Cinema_Halls_ID )
BEGIN
PRINT'This Cinema Hall is Already Booked'
Rollback Transaction;
return
END
ELSE IF (#Showtime_DATE >= #Release_Date and #Showtime_Date<= #Last_Date)
BEGIN
PRINT'Movie Showtime not in Range'
Rollback Transaction;
return
END
I think this is what you are looking for. The changes/improvements/best practices are:
Uses set-based logic, which you should always aim to do in a relational database.
Uses Inserted as a table rather than a single row
Semi-colon line terminators
set nocount on
Uses throw
Uses [] instead of ""
Fixed "in range" logic and detection of duplicate logic
CREATE TRIGGER Trigger_Movie_Shedule
ON [Movie Schedule]
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (
SELECT 1
FROM [Movie Schedule] S
-- Restrict the check to the inserted/updated records
INNER JOIN Inserted I on I.Showtime_ID = S.Showtime_ID and I.Cinema_Halls_ID = S.Cinema_Halls_ID
GROUP BY S.Showtime_ID, S.Cinema_Halls_ID
-- If more than one row exists we have a problem Houston
HAVING COUNT(*) > 1
) BEGIN
-- Rolls back, returns and provides an error message all in one.
THROW 51000, 'This Cinema Hall is Already Booked',1;
END; ELSE IF EXISTS (
SELECT 1
FROM Inserted I
INNER JOIN Movie M ON M.Movie_ID = I.Movie_ID
INNER JOIN ShowTime S ON S.ShowTime_ID = I.ShowTime_ID
-- WHERE S.Showtime_DATE >= M.Release_Date and S.Showtime_Date < M.Last_Date
-- Think you logic detects when it *is* in range, whereas the error is when its out of range
WHERE S.Showtime_DATE < M.Release_Date or S.Showtime_Date > M.Last_Date
) BEGIN
-- Rolls back, returns and provides an error message all in one.
THROW 51000, 'Movie Showtime not in Range',1;
END;
END;
Note: I highly recommend reading Using Inserted and Deleted as it explains very clearly how to write triggers.
I'm trying to replicate a foreign key across two servers using trigger. I know using trigger across 2 servers is not the best practice but my company on gives me read-only access to their database which I need to relate to my application.
I have DB1 which is my local database and it is attached to DB2 using linked server. I want trigger to check if a specific ID from a DB2_table on DB2 exists before executing an INSERT on DB1_table where the ID from DB2_table will act as a foreign key.
CREATE TRIGGER trigger_DB1_Table_Insert
#ID
BEFORE INSERT ON DB1_Table
AS
BEGIN
if exists(Select ID from DB2_Table where ID = #ID)
--execute insert
END
GO
I would actually recommend using a check constraint instead of a trigger. Check Constraints are designed to enforce data integrity and are a semantically better option. The example below creates some working tables, then creates a function which will check if the record exists in the other table.
The check constraint then uses the function and returns an error if the value doesn't exist.
CREATE TABLE dbo.OtherTable(
id INT
)
CREATE TABLE dbo.a(
id INT IDENTITY(1,1)
,OtherTableId INT
)
GO
INSERT INTO OtherTable (id) VALUES (1), (2), (3)
GO
-- Function will check if the ID exists in the other table
CREATE FUNCTION dbo.CheckOtherTableId(
#OtherTableId INT
)
RETURNS BIT
AS BEGIN
RETURN
(
SELECT
CASE
WHEN EXISTS
(
SELECT 1
FROM OtherTable
WHERE id = #OtherTableId
)
THEN 1
ELSE 0
END
)
END
GO
-- Add check constraint
ALTER TABLE a WITH CHECK
ADD CONSTRAINT [CK_OtherTable] CHECK (1=dbo.CheckOtherTableId(OtherTableId))
GO
-- Test should work
INSERT INTO a (OtherTableId) values (1)
Go
-- Test should fail
INSERT INTO a (OtherTableId) values (8)
GO
I have a problem. I am creating a trigger which will prompt the user to not create a purchase order with a higher cost to their selling cost. I have declared a column on my script but its still showing this error:
Msg 207, Level 16, State 1, Procedure _trgZSCheckPrice, Line 31 [Batch Start Line 7]
Invalid column name 'fExclPrice'
The two columns are #Check and #Excl
I have attached my code below any help is advisable:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER _trgZSCheckPrice
ON [dbo].[_btblInvoiceLines]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE
#Valid int,
#ValidPO int,
#DocType int,
#DocState int,
#Check int,
#Excl float,
#POPrice float
SELECT
#Check = ubIICheck,
#Excl = fExclPrice,
#POPrice = fUnitPriceExcl
FROM
INSERTED
SELECT
#Excl = fExclPrice,
#Check = ubIICheck
FROM
stkitem A
INNER JOIN
_etblPriceListPrices B ON A.StockLink = B.iStockID
SELECT
#POPrice = fUnitPriceExcl
FROM
_btblInvoiceLines C
LEFT JOIN
InvNum D ON C.iInvoiceID = D.AutoIndex
BEGIN
IF (#DocType = 5 AND #DocState <> 7) AND #CHECK = 1
BEGIN
IF #Excl > #POPrice
BEGIN
RAISERROR ('Message from Management:
You are not allowed to Purchase above Selling Cost.
The transaction will be rolled back. ', 16, 1)
ROLLBACK TRANSACTION
END
END
END
END
It seems like ideally, here, you'd be implementing this as a multi-table CHECK constraint (in fact, in standard SQL, these are called ASSERTIONs. So far as I'm aware, only Postgre implements them).
If you're happy to trade away the ability to completely control the error message, I'd usually prefer to implement this in a declarative manner rather than relying on a trigger.
Here's how to do such a check with an indexed view. First a couple of tables that are somewhat like your problem domain (but not very fleshed out since you didn't put any definitions in your question):
create table dbo.ListPrices (
ID int not null,
Price decimal(12,4) not null,
constraint PK_ListPrices PRIMARY KEY (ID)
)
create table dbo.Orders (
ID int not null,
ListPriceID int not null,
MyPrice decimal(12,4) not null,
constraint PK_Orders PRIMARY KEY (ID),
constraint FK_Orders_ListPrices FOREIGN KEY (ListPriceID)
references dbo.ListPrices (ID)
)
go
insert into dbo.ListPrices (ID,Price) values (1,12.50),(2,25.00)
And now we create a special helper table. It's not needed if you already have a suitable table (such as a numbers table) in your database:
create table dbo.Two (
n int not null,
constraint PK_Two PRIMARY KEY (n),
constraint CK_Two_Only CHECK (n in (1,2))
)
go
insert into dbo.Two (n) values (1),(2)
And now we create the view:
go
create view dbo.DRI_NoOrderPricesOverListPrices
with schemabinding
as
select
1 as p /* Constant */
from
dbo.Two t
cross join
dbo.Orders o
inner join
dbo.ListPrices lp
on
o.ListPriceID = lp.ID
where
/*Conditions for failure*/
o.MyPrice > lp.Price
go
create unique clustered index IX_NoOrderPricesOverListPrices
on DRI_NoOrderPricesOverListPrices(p)
The key feature here is that the view joins all of the tables we're interested in together and we can put whatever conditions we like in the where clause, referencing multiple tables, comparing column values, etc.
The conditions we're specifying is for what shouldn't be allowed in the database. So, we're saying we should be able to insert a row in Orders provided that its price is less than or equal to the price in line items.
And we can. This insert succeeds:
insert into Orders (ID,ListPriceID,MyPrice) values (1,2,17.00)
And this one fails:
insert into Orders (ID,ListPriceID,MyPrice) values (2,1,17.00)
Msg 2601, Level 14, State 1, Line 42
Cannot insert duplicate key row in object 'dbo.DRI_NoOrderPricesOverListPrices' with unique index 'IX_NoOrderPricesOverListPrices'. The duplicate key value is (1).
(As I said at the top, we don't get so much control over the error message - but making a good choice of name here should make it reasonable to deduce what's happening and directly exposing SQL Server error messages to the users is something I'd generally try to avoid)
I'm trying to write an SQL function that given a name of a game, it will allow me to search the table of games for that particular game and returns all the info about that game.
This is the code for the Games table:
CREATE TABLE Games(
game_id INT IDENTITY PRIMARY KEY,
name VARCHAR(50),
release_date VARCHAR(50),
rating VARCHAR(5),
min_age INT,
development_team_email VARCHAR(50) FOREIGN KEY REFERENCES Development_Teams,
release_conference INT FOREIGN KEY REFERENCES Conferences
)
And here is the what I could come up with when I was trying to write the function:
create function SearchGames(#game_name varchar(50))
returns table
begin
declare #game
Select (*)
From Games
where Games.name = #game_name
return #game
end
I'm getting a lot of syntax errors and I don't know what I'm doing wrong. Any help appreciated.
Use inline table valued function syntax and add schema:
create function dbo.SearchGames(#game_name varchar(50))
returns table
AS
RETURN (Select *
From Games
where Games.name = #game_name);
SqlFiddleDemo
If you use stored procedure you need to use:
CREATE TABLE ...;
INSERT INTO ... EXEC stored_procedure #args;
-- another operation on stored procedure resultset
while with inline table function you just:
SELECT * FROM dbo.SearchGames('aaa') GROUP BY ... HAVING ... ORDER BY;
I wouldn't recommend using a function for this, but rather a stored procedure:
Create Proc spSearchGames (#game_name Varchar (50))
As Begin
Select *
From Games
Where name = #game_name
End
Go
And executing it:
Exec spSearchGames 'YourGameName'