suppose i am calling a Stored Procedure and sending some params. the Stored Procedure will update a table and a trigger is there for that table. so when Stored Procedure update table then i want which user is updating the table but i am not using sql server user name rather i will send user names to SP who will update the table. so before update i can store that user name in local temp table and query that local temp table from trigger to get that user name. i hope it is possible but i want to other good option to achieve this job. so please share idea. thanks
You can encode the user name in the procedure into the session using SET CONTEXT_INFO
This can be read in the trigger by CONTEXT_INFO
This is concurrency safe: each session/call is isolated from any other.
And no need for a temp table or such.
DECLARE #context varbinary(100) = CAST('foobar' AS varbinary(100));
SET CONTEXT_INFO #context;
SELECT CAST(CONTEXT_INFO() AS varchar(100));
Related
I need to create a stored procedure in SQL Server using the Dbeaver software and I am wondering if you have any experience with creating one with this software since I am using Mac and I am not able to install SQL Server Management Studio.
The case is that I will need to update the field for one user across all the courses assigned to that user (about 20).
It will be something like this :
UPDATE tablename
SET date = '2018-03-15'
WHERE UserID = 1234 AND ProgramID = 1234;
It is updating the date fine.
From this point, my question is about would it be better to use UPDATE or something else since they just need to view the report for this data inside of UI? How would you start the script for this procedure and what would you use? Thanks
From your conclusive question I suppose you want the syntax to create a procedure which you can learn from so many sites available with great content. To create procedure for this specific activity your procedure will look something like this. You can dynamically add date, user's Id and program's Id, if you want to take the report for some other date depending on your needs. Hope this helps.
CREATE OR REPLACE PROCEDURE updatedate(#dateupdate datetime, #ProgramID INT, #UserID INT)
AS
BEGIN
UPDATE tablename
SET date = #dateupdate
WHERE UserID = #UserID AND ProgramID = #ProgramID;
END;
To execute your procedure just replace the variables with the values you want in below query.
updatedate(#dateupdate, #ProgramID, #UserID)
This is an example for MySQL but should work with any database:
Right Click on a database and choose Create -> Procedure
Fill in the details of what you want for the procedure.
Open up the procedure editor and go to Source tab and paste your source
Save
Persist
I have one Stored Procedure lets call it ABC, which generates a temporary table ##ref1. This procedure will execute only if the weekday is equal to a MONDAY.
I have another Stored Procedure let call it XYZ, which generates an output table which a union of ##ref1 from ABC and similarly few other stored procedure.
I get an error saying ##ref1 is an invalid object in the XYZ Stored Procedure as ##ref1 is only created on a Monday.
How can I rectify this error in the Stored Procedure XYZ? Any help would be appreciated.
Thank you.
Instead of using global temporary table, why don't you use a physical table.
In your case, the global temporary table must have been deleted.
Global temporary tables are visible to any user and any connection after they are created, and are deleted when all users that are referencing the table disconnect from the instance of SQL Server.
If you create the global temporary table ##employee, any user in the
database can work with this table. If no other user works with this
table after you create it, the table is deleted when you disconnect.
If another user works with the table after you create it, SQL Server
deletes it after you disconnect and after all other sessions are no
longer actively using it.
You can get more details on this here and here
If you really need to use global temporary table then something like this should work:
create stored procedure xyz as
begin
create table #result (id int)
if object_id('tempdb..##ref1 ') is not null
insert into #result
select * from ##ref1
-- do you stuff here
drop table #result
end
I have a stored procedure to run after a set of tables, all belonging to the same schema [DATA_Countries], is dropped and then re-inserted.
The operation is performed by another application, which drops and recreates the target table, over which I have no control.
Since the table is dropped and recreated each time, I can not use triggers on each target table.
Is there a way to get a trigger for each time a table is inserted into a specific schema, to return the name of such table and launch a parametrized stored procedure?
Thanks!
Yes, You can create DDL Triggers on SQL Server to track the DDL Changes. For example, If I want to track the changes in Stored Procedures on my Database AdventureWorks, I can create a trigger like this
CREATE TRIGGER td_ProcTrack
ON AdventureWorks
FOR CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE
AS
BEGIN
<my code>
END
Refer this Article for more detailed examples
If we have an alter table statement within a stored procedure. Will it just affect that session or will it affect all sessions?
We use the alter table to disable the triggers that occur because we don't want them run when the stored procedure occurs but want the update triggers to run at all other times.
Cheers,
"Alter table" is an DDS operation - it will change the DB structure for all connections.
Here is a trick: create temp table with unique name like #no_triggers_for_[procname] at the beginning of your sp and check for it's existence within triggers.
I'm working on the next update for StackQL.
One thing I want to do is have the ability to query over several releases. So when I loaded the October data, for example, I didn't delete the old September database. It's still out there. In fact, you can even still query it by including the database name like this:
select top 10 * from SO_Sept09..Posts
This will be even more important as they start providing data for ServerFault and SuperUser.
But I don't like having a whole bunch of databases out there to support this. I'd much rather put all the data in the same database and separate each distinct set into it's own schema. But to make this possible, I need to be able to set a default schema as part of the stored procedure that runs the query, based on a parameter passed to the stored procedure that tells it which database the user selected from a future drop down list to appear in the tool bar.
Queries at StackQL are eventually just passed to the exec() function like this:
exec(#QueryText)
Is there anything I can do either in the stored procedure or prepend to the QueryText string (ala USE [DatabaseName]) to set the default schema used in a query?
There are pieces of how to do this in various places here, but not altogether. The way to do this is:
Make a unique login & user for each schema
Make these users the owners of each different schema.
Set each such user's default schema to be the schema that they own.
Use the syntax EXECUTE ('sql commands') AS USER = 'schema-owner' to execute your SQL commands in the context of that default schema.
The following script demonstrates this:
--====== Create the Login for the User:
CREATE LOGIN [UserTest1] WITH PASSWORD='whatever', DEFAULT_DATABASE=[TestUsers], DEFAULT_LANGUAGE=[us_english]
GO
--====== Make a User for the Login:
CREATE USER [UserTest1] FOR LOGIN [UserTest1]
GO
--====== Make a Schema owned by the User and default to it:
-- (I assume that you already have the schemas)
CREATE SCHEMA [UserTest1] AUTHORIZATION [UserTest1]
GO
ALTER USER [UserTest1] WITH DEFAULT_SCHEMA=[UserTest1]
GO
--====== Make a sProc in dbo
CREATE PROCEDURE [dbo].[TestSchema_Exec] AS
SELECT 'executing in schema [dbo]'
GO
--====== Make a similar sProc in New Schema
CREATE PROCEDURE [UserTest1].[TestSchema_Exec] AS
SELECT 'executing in schema [UserTest1]'
GO
--========= Demonstrate that we can switch Default Schemas:
EXEC('TestSchema_Exec')
EXEC('TestSchema_Exec') AS USER = 'UserTest1'
Other than modifying #QueryText itself, the only thing I can think of is a user's default schema:
ALTER USER SO_Sept09_Reader WITH DEFAULT_SCHEMA = SO_Sept09
...and then connect as a different user for each schema you want to use. Hackity hack.
But if your query is dynamically constructed anyway (and I'm sure you know why that's often not a great idea), it might be easiest to just add a schema placeholder to the query text, and pass the schema name along with the query to a replacement function.
Another possibility is to generated copies of each SP in each schema, the unmodified table name in an SP refers to tables in the same schema.
Note this doesn't work with dynamic SQL inside such an SP:
CREATE PROCEDURE schema_a.SP
#somesql AS varchar(MAX)
AS
BEGIN
EXEC ( #somesql )
END
CREATE PROCEDURE schema_b.SP
#somesql AS varchar(MAX)
AS
BEGIN
EXEC ( #somesql )
END
Won't work, because the schema affinity is lost inside the EXEC.
While this:
CREATE PROCEDURE schema_a.SP
AS
BEGIN
SELECT * FROM tbl -- Will use schema_a.tbl first
END
CREATE PROCEDURE schema_b.SP
AS
BEGIN
SELECT * FROM tbl -- Will use schema_b.tbl first
END
works fine.
Similarly:
EXEC ( 'EXEC schema_a.SP' )
would obviously work fine.
Untried, but: could you combine the different schemas' data into one view, and add a column calling out the schema name?
CREATE VIEW AllPosts AS
SELECT Data1, Data2, 'Sept09' AS Partition FROM SO_Sept09..Posts
UNION ALL
SELECT Data1, Data2, 'Oct09' AS Partition FROM SO_Oct09..Posts
...
SELECT * FROM AllPosts WHERE Partition = 'Sept09'
SELECT * FROM dbo.AllPosts('Sept09') -- if use table-valued function instead
Okay, I have a new way to do this that might work a little better for me. It's a variant on my comment to Michael Petrotta's answer:
But it does give me the idea to maybe have several users and pick the connection string on the fly.
What I will do is have just one user for executing these queries, but I will swap out the connection string on the fly to specify the correct Initial Catalog.