SQL Server : Create Procedure in DB without using [GO] - sql-server

I want to execute this (simplified) query using node-mssql that executes in SQL Server 2017 fine:
USE [Journal]
[GO]
CREATE PROCEDURE [dbo].[EventDelete]
#NotificationID INT
AS
DELETE Notification
WHERE NotificationID = #NotificationID
[GO]
node-mssql declares syntax error using [GO] and requires semicolon, therefore I try this:
USE [Journal];
CREATE PROCEDURE [dbo].[EventDelete]
#NotificationID INT
AS
DELETE Notification
WHERE NotificationID = #NotificationID;
Now we get error:
CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
So let's try this:
CREATE PROCEDURE [Journal].[dbo].[EventDelete]
#NotificationID INT
AS
DELETE Notification
WHERE NotificationID = #NotificationID;
Now we get
RequestError: 'CREATE/ALTER PROCEDURE' does not allow specifying the database name as a prefix to the object name.
Naturally without any DB declaration it attempts to attach to the master error:
CREATE PROCEDURE permission denied in database 'master'.

So writing the question really works at setting one's thoughts straight.
The reason is the stored procedure requires to be created in one batch, which [GO] signifies, with nothing else.
Execute USE [Journal] as one batch using the .batch('USE [Journal]') method and then the SQL to CREATE PROCEDUCE as a new .batch(...) execution, sequentially.
Unless there is another method within node-mssql which allows for multi-batch executions?

Related

Trigger cannot be created in Microsoft SQL Server Management Studio

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...

DB2 Stored Procedure Returning SQLCODE=-440, SQLSTATE=42884

I am currently using RazorSQL to test queries with IBM DB2. Right now, I am stuck on an issue with creating procedures
I have the following procedure. I create this procedure as an admin user called db2inst1:
CREATE OR REPLACE PROCEDURE CANCEL_ACTIVITY (IN application_handle INTEGER)
LANGUAGE SQL
BEGIN
DECLARE UOW_ID INTEGER;
DECLARE ACTIVITY_ID INTEGER;
FOR v AS cur1 CURSOR FOR
SELECT UOW_ID, ACTIVITY_ID FROM TABLE(SYSPROC.MON_GET_ACTIVITY(application_handle, -1))
DO
CALL WLM_CANCEL_ACTIVITY(application_handle, v.uow_id, v.activity_id);
END FOR ;
END
Now, I log onto my regular user called applicationtest which is NOT an admin. If I run the following:
CALL CANCEL_ACTIVITY(12345)
I get the following error:
DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884, SQLERRMC=CANCEL_ACTIVITY;PROCEDURE, DRIVER=4.16.53
According to IBM, it's caused by:
NO AUTHORIZED routine-type BY THE NAME routine-name HAVING COMPATIBLE ARGUMENTS WAS FOUND
Looking at this question, I ran this debug code to check if the users are the same, and it does not appear to be the same, because the results are:
| ROUTINESCHEMA
1 | db2inst1
2 | DB2INST1
Logically, ROUTINESCHEMA should have my regular user applicationtest in it, right?
I even ran the following:
GRANT EXECUTE ON PROCEDURE CANCEL_ACTIVITY TO PUBLIC;
To see if it would help, but still, same error.
I also tried to create the procedure using applicationtest, but as expected, I don't have the privileges required to do so.
EDIT:
I just specified DB2INST1.CANCEL_PROCEDURE(12345), and now I am getting the following error:
2016-11-18 11:27:34.983 -0800 [ERROR|01c56|] :: Java::ComIbmDb2JccAm::SqlSyntaxErrorException : DB2 SQL Error: SQLCODE=-551, SQLSTATE=42501, SQLERRMC=APPLICATIONTEST;EXECUTE;DB2INST1.CANCEL_ACTIVITY, DRIVER=4.16.53
I guess that user applicationtest doesn’t have permission to execute that procedure?
I have two questions:
Is it possible to not have to call DB2INST1 before calling the procedure? So I can just call it like this CALL CANCEL_PROCEDURE(..) instead of CALL DB2INST1.CANCEL_ACTIVITY. I feel like this would remove a lot of the ambiguity..
How do I grant applicationtest the necessary privilege to call the procedure?
You have two issues here:
The schema of the stored procedure is the implicit schema of the user that created the procedure. In this case the schema name is 'db2inst1'. When you connect with the other user, 'applicationtest' the implicit schema is the same name of the user. Then you have the following possibilities:
Set the schema to db2inst1: https://www.ibm.com/support/knowledgecenter/es/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0001016.html
Call the stored procedure with schema.name: db2inst1.cancel_activity
Set the path, including db2inst1 on it: https://www.ibm.com/support/knowledgecenter/es/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0001014.html
Between, the previous three options, I personally recommend the second one schema.name.
The other problem is the execution permission. When you create a procedure, you have to grant execution to other users / groups. In this case, db2inst1 user created the procedure, but just this user (or someone with DBADM authority) can execute it.
Because you are connecting with the other user you have to grant the execution (https://www.ibm.com/support/knowledgecenter/es/SSEPGG_11.1.0/com.ibm.db2.luw.sql.ref.doc/doc/r0007699.html):
db2 grant execution on procedure db2inst1.cancel_activity to user applicationtest

Execute sql task mapping variables in ssis

INSERT INTO [DEV_BI].dbo.[DimAktivitet]([Beskrivning],[företag],[Projektnummer],[Aktivitet],
loaddate)
SELECT NULL,
a.DATAAREAID,
a.PROJID,
a.MID_ACTIVITYNUMBER,
GETDATE()
FROM [?].dbo.[v_ProjCostTrans_ProjEmplTrans] a
LEFT OUTER JOIN [DEV_BI] .dbo.[DimAktivitet] b ON a.MID_ACTIVITYNUMBER = b.Aktivitet
AND a.DataAreaID = b.företag
AND a.ProjID = b.Projektnummer
WHERE b.Aktivitet_key IS NULL
I have this above sql code in execute sql task and in the parameter mapping i have mapped a variable named user::connectionstring with data type nvarchar , parameter name = 0. Im getting this following error.
[Execute SQL Task] Error: Executing the query "insert into [DEV_BI].dbo.[DimAktivitet]([Beskrivni..." failed with the following error: "Invalid object name '?.dbo.v_ProjCostTrans_ProjEmplTrans'.". Possible failure reasons: Problems with the query, "ResultSet" property not set correctly, parameters not set correctly, or connection not established correctly.
please someone help me to solve this.
It appears you are trying to change the database based on a variable. The Execute SQL Task can only use parameters as filters in the WHERE clause. This behavior is described in this TechNet article. For instance, you could do this:
insert into [DEV_BI].dbo.[DimAktivitet]([Beskrivning],[företag],[Projektnummer],[Aktivitet],loaddate)
select null,a.DATAAREAID,a.PROJID,a.MID_ACTIVITYNUMBER,GETDATE() from
[DEV_BI].dbo.[v_ProjCostTrans_ProjEmplTrans] a
left outer join
[DEV_BI] .dbo.[DimAktivitet] b
on a.MID_ACTIVITYNUMBER = b.Aktivitet AND a.DataAreaID = b.företag AND a.ProjID = b.Projektnummer
where b.Aktivitet_key is null
AND b.SomeFilterCriteria = ?;
If you really want to vary the database based on a variable, then you have three options:
Vary the Connection Manager connection string to your database connection based on an expression as described in a blog post. This is the best solution if you are only changing the database and nothing else.
Generate the entire SQL code as a variable and execute a variable as the SQL command instead of passing variables to the Execute SQL Command. This is described in this blog post under the section "Passing in the SQL Statement from a Variable".
Create a stored procedure, pass the parameter to the stored procedure, and let it generate the SQL it needs on the fly.

how to create database using java code?

I want to create a database using java code, I have the database script file, I will read in a string and I will execute it but I want to know if I can use executequery or executeupdate???
and if this method is right or there is another one???
The method signature for the executeUpdate method of the Statement interface is:
int executeUpdate(String sql)
throws SQLException
executeUpdate executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
So to define a table or define an index, you would pass the SQL string to the executeUpdate method.
You can only execute one SQL statement at a time using the executeUpdate method, so if you're reading a file with more than one SQL statement, you'll have to parse the file and execute each SQL statement, one at a time.

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