Trigger cannot be created in Microsoft SQL Server Management Studio - sql-server

I'm trying to run this trigger that is suppose to update a row in my customers table after a row is updated in the same table.
CREATE TRIGGER [project].updateFreeShipping
ON [project].[customers]
AFTER UPDATE
AS
BEGIN
UPDATE [project].[customers]
SET NextShippingIsFree = 1
WHERE Email IN (SELECT TOP 5 Email FROM dbo.Top10byMoney)
END
It throws the following error:
Msg 8197, Level 16, State 4, Procedure updateFreeShipping, Line 2
The object 'project.customers' does not exist or is invalid for this operation
Screenshot:

This is a clear and classical error that is raised when you execute a statement in another database that the one you usually use. Very often, beginners does not verify the contexteual database and try to create objets in master which is the default one in SSMS. Remember that SQL Server is a multi-database multi-schema RDBMS and does not require any DBlink to execute SQL scripts from one DB to another... So make a great attention to which database you contextually use !
To avoid such trouble, begin your script with the USE statement, like :
USE MyDatabase;
GO
CREATE TRIGGER [project].updateFreeShipping
ON [project].[customers]
AFTER UPDATE
AS
...
I agree to all others comments about the logic of your code which has no sense...

Related

EF Core idempotent migration script fails despite check on applied migration

I am using EF Core (3.1.15). In a previous migration (also created in 3.1.15), a column was referenced that was dropped later on. The idempotent script does check if the migration was performed on the database (which it is, and the reference still shows in the __EFMigrationsHistory table). However the check doesn't have the expected result and the script due to the inexistent column.
Q: why is the inexistent column tripping the execution of the SQL script?
Script was created with
dotnet-ef migrations script -i -o migrations.sql
Relevant part of the automated script that fails, where ReferenceToLedgerId is the column dropped in later migration:
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;
Error:
Msg 207, Level 16, State 1, Line 3
Invalid column name 'ReferenceToLedgerId'
When running the following SQL query, the result comes back as expected:
SELECT *
FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger'
MigrationId
ProductVersion
20210612052003_CLedger
3.1.15
The database is Azure SQL Database. Script doesn't fail on local SQL dev database. A dozen migrations have been applied since then, and only now the script fails.
Below was the call that created the specific script:
migrationBuilder.Sql("UPDATE LedgerTable set LedgerId = ReferenceToLedgerId", true);
I tried to place the table and column names in square brackets, but that made no difference (eg. [ReferenceToLedgerId]. The script fails in Azure DevOps release when using SQLCMD and also fails when using Azure Data Studio, both accessing the Azure SQL Database.
Additional check
I changed the script to do a quick check:
PRINT '#Before IF'
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
PRINT '#Within IF'
--UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;
PRINT '#After IF'
To which I get the following result:
Started executing query at Line 1
#Before IF #After IF
Total execution time: 00:00:00.010
If I uncomment the UPDATE statement it fails again. So I can only conclude that the code path works as intended, but that the server still checks for the existence of the column. I am not familiar with SQL to understand why this would be, or why it only fails for this one line while the column itself is referenced in other lines of the SQL script without it failing.
That batch will fail on every version of SQL Server. eg
use tempdb
go
create table __EFMigrationsHistory(MigrationId nvarchar(200))
create table LedgerTable(LedgerId int)
go
insert into __EFMigrationsHistory(MigrationId) values (N'20210612052003_CLedger')
go
IF NOT EXISTS(SELECT * FROM [__EFMigrationsHistory] WHERE [MigrationId] = N'20210612052003_CLedger')
BEGIN
UPDATE LedgerTable SET LedgerId = ReferenceToLedgerId
END;
Fails with
Msg 207, Level 16, State 1, Line 8
Invalid column name 'ReferenceToLedgerId'.
Because the batch cannot be parsed and compiled. It's simply not legal to reference a non-existent table or column in a TSQL batch.
You can work around this by using dynamic SQL, so that the batch referencing the non-existent column is not parsed and compiled unless the migration is being applied.
migrationBuilder.Sql("exec('UPDATE LedgerTable set LedgerId = ReferenceToLedgerId')", true);
This is documented here:
Tip
Use the EXEC function when a statement must be the first or only
one in a SQL batch. It might also be needed to work around parser
errors in idempotent migration scripts that can occur when referenced
columns don't currently exist on a table.
https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/operations

removing an object from Publication database sys.sp_droparticle and sp_dropsubscription

SQL Server Admin is not my forte. So please bear with while I explain this
A SQL Server 2012 cluster is involved in a Change data capture ( CDC ) effort using a 3rd party CDC utility. for it to work replication needs to be turned on, without replication CDC will not work. The CDC taps some 2000+ odd tables from SQL Server in a database Db1. Out of these we found out that some 200+ tables undergo truncate and load as against increments. So we removed those from our CDC lists but since replication is turned on at DB Level we also need to remove these from publication database so that truncates happening to this exception list wont need replication switched off DB level ( aka truncates to these tables and replication can co-exist. As its known, for truncates to happen we need to switch off replication. The code is in prod so replacing truncate by delete is not an option now besides the fact that for billion row tables deletes are going to be expensive & time consuming )
The above is the requirement. So based on that if a better solution can be conceived do let me know
What I tried :
EXEC sys.sp_droparticle #publication = 'pub', #article = 'art', #force_invalidate_snapshot = 1
Error I get
Msg 14013, Level 16, State 1, Procedure sp_MSrepl_droparticle, Line 104 [Batch Start Line 2]
This database is not enabled for publication.
Another SP
DECLARE #subscriber AS sysname;
EXEC sp_dropsubscription #publication = 'AR_PUBLICATION_00010', #article = 'BPA_BRGR_RUL_GRP_R' ,#subscriber=#subscriber
Msg 14013, Level 16, State 1, Procedure sp_MSrepl_dropsubscription, Line 55 [Batch Start Line 1]
This database is not enabled for publication.
But using GUI I am able to uncheck the tables I dont want in that publication. ( right click publication --> properties --> articles --> check /uncheck whatever you want excluded ) . I dont have any subscription just there is a publication.
Whatever code I ran through GUI above I can def. run through T-SQL But I dont know what code was it that was run ? How do I get this done using a scripting approach. I have 200+ tables to deal with and unchecking em 1 by 1 ain't helping
Nearly four years late, but in case it helps anyone... I think you want sp_dropmergearticle not sp_droparticle.
EXEC sys.sp_dropmergearticle #publication = 'pub', #article = 'art', #force_invalidate_snapshot = 1
I was getting an identical error message using sp_droparticle, but sp_dropmergearticle removed the table from the publication and allowed me to delete it.
Whatever code I ran through GUI above I can def. run through T-SQL But I dont know what code was it that was run ? How do I get this done using a scripting approach.
SSMS does not have a special API. Everything it does, it does through TSQL. So use SQL Profiler to watch what SSMS does, and capture the script.

SQL Server Msg 2108

I created and altered a trigger and everything worked well, but when I started the SQL Server Management Studio later on, the following error appeared:
Msg 2108, Level 15, State 1, Procedure store_110, Line 43
Cannot create trigger on 'IT_ServerDB.dbo.Users' as the target is not in the current database.
Cannot create trigger on 'IT_ServerDB.dbo.Users' as the target is not in the current database.
It seems ,you are using three part naming like below
'IT_ServerDB.dbo.Users
use two part naming
use IT_ServerDB
go
create trigger triggername
on
and rest of syntax

Unable to update a table using sql query in sql server

I use sql server 2014.
I have a table in my ManuDB database called (waqf).
I am trying to update the table
but not allowed and a message (invalid object name waqf) appears.
I don't know what is the reason although I have a table called waqf.
Because you are executing the statement in Master Database as shown in the snip shot.
select the correct database from drop down list shown in picture or execute the following statement.
USE ManuDB
GO
UPDATE ......
From the drop down list of database; set it to ManuDB.
At the moment, it's pointing to Master which doesn't have your table.
Type USE <yourdatabasename> before your update statement

Cannot find the object because it does not exist or you do not have permissions. Error in SQL Server

I have a database and have a Sql script to add some fields to a table called "Products" in the database.
But when i am executing this script, I am getting the following error:
Cannot find the object "Products" because it does not exist or you do not have permissions
Why is the error occurring and what should I do to resolve it?
I found a reason why this would happen. The user had the appropriate permissions, but the stored procedure included a TRUNCATE statement:
TRUNCATE TableName
Since TRUNCATE deletes items without logging, you (apparently) need elevated permissions to execute a stored procedure that contains it. We changed the statement to:
DELETE FROM TableName
...and the error went away!
Are you sure that you are executing the script against the correct database? In SQL Server Management studio you can change the database you are running the query against in a drop-down box on one of the toolbars, or you can start your query with this:
USE SomeDatabase
It can also happen due to a typo in referencing a table such as [dbo.Product] instead of [dbo].[Product].
Does the user you're executing this script under even see that table??
select top 1 * from products
Do you get any output for this??
If yes: does this user have the permission to modify the table, i.e. execute DDL scripts like ALTER TABLE etc.? Typically, regular users don't have this elevated permissions.
Look for any DDL operation in the script.
Maybe the user does not have access rights to run changes.
In my case it was SET IDENTITY_INSERT tblTableName ON
You can either add db_ddladmin for the whole database or for just the table to solve this issue (or change the script)
-- give the non-ddladmin user INSERT/SELECT as well as ALTER:
GRANT ALTER, INSERT, SELECT ON dbo.tblTableName TO user_name;
It could also be possible that you have created the "Products" in your login schema and you were trying to execute the same in a different schema (probably dbo)
Steps to resolve this issue
1)open the management studio
2) Locate the object in the explorer and identify the schema under which your object is? ( it is the text before your object name ). In the image below its the "dbo" and my object name is action status
if you see it like "yourcompanydoamin\yourloginid" then you should
you can modify the permission on that specific schema and not any other schema.
you may refer to "Ownership and User-Schema Separation in SQL Server"
I've been trying to copy a table from PROD to DEV but get an error:
"Cannot find the object X because it does not exist or you do not have permissions."
However, the table did exist, and I was running as sa so I did have permissions.
The problem was actually with CONTRAINTS. I'd renamed the table on DEV to be old_XXX months ago. But when I tried to copy the original one over from PROD, the Defaut Constraint names clashed.
The error message was misleading
You can right click the procedure, choose properties and see which permissions are granted to your login ID. You can then manually check off the "Execute" and alter permission for the proc.
Or to script this it would be:
GRANT EXECUTE ON OBJECT::dbo.[PROCNAME]
TO [ServerInstance\user];
GRANT ALTER ON OBJECT::dbo.[PROCNAME]
TO [ServerInstance\user];
This could be a permission issue. The user needs at least ALTER permission to truncate a table.
Another option is to call DELETE FROM instead of TRUNCATE TABLE, but this operation is slower because it writes to the Log file, whereas TRUNCATE does not write to the log file.
The minimum permission required is ALTER on table_name. TRUNCATE TABLE
permissions default to the table owner, members of the sysadmin fixed
server role, and the db_owner and db_ddladmin fixed database roles,
and are not transferable. However, you can incorporate the TRUNCATE
TABLE statement within a module, such as a stored procedure, and grant
appropriate permissions to the module using the EXECUTE AS clause.
Sharing my case, hope that will help.
In my situation inside MY_PROJ.Database->MY_PROJ.Database.sqlproj I had to put this:
<Build Include="dbo\Tables\MyTableGeneratingScript.sql" />
In my case I was running under a different user than the one I was expecting.
My code passed 'DRIVER={SQL Server};SERVER=...;DATABASE=...;Trusted_Connection=false;User Id=XXX;Password=YYY' as the connection string to pypyodbc.connect(), but it ended up connecting with the credentials of the Windows user that ran the script instead of the User Id= from the connection string.
(I verified this using the SQL Server Profiler and by putting an invalid uid/password combination in the connection string - which didn't result in an expected error).
I decided not to dig into this further, since switching to this better way of connecting fixed the issue:
conn = pypyodbc.connect(driver='{SQL Server}', server='servername',
database='dbname', uid='userName', pwd='Password')
In my case the sql server version on my localhost is higher than that on the production server and hence some new variables were added to the generated script from the localhost. This caused errors in creating the table in the first place.
Since the creation of the table failed, subsequent query on the "NON EXISITING" table also failed.
Luckily, in among the long list of the sql errors, I found this "OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF" to be the new varialbe in the script causing my issue. I did a search and replace and the error went away.
Hope it helps someone.
The TRUNCATE statement was my first problem, glad to find the solution here. But I was using SSIS and trying to load data from another database, and it failed with the same error on any table that used IDENTITY to create an auto-incrementing ID. If I was scripting it myself I'd first need to use the command SET IDENTITY_INSERT tablename ON, and then SET IDENTITY_INSERT tablename OFF when the table update was done. But this requires ALTER permissions on the table, which I do not have. Hence the error message in SSIS on the table load (even though the previous step had just deleted all the data out of the table.)
You receive this error, when you use an ORM like GORM (https://gorm.io/) in Go for example.
When you try to create a struct and accidentally pass the ID (primary key) although it's inserted automatically.
Rich features IDE like Visual Studio Code make this mistake happen easily:
if tx := db.Create(&myStruct{
Ts: Time.Now(),
ID: 42,
}); tx.Error != nil {
t.Fatal(tx.Error)
}
You can still use auto-filling by Visual Studio Code, but delete your entry for your model's primary keys:
if tx := db.Create(&myStruct{
Ts: Time.Now(),
}); tx.Error != nil {
t.Fatal(tx.Error)
}

Resources