How to get Database Name in a Logon Trigger using EVENTDATA() - tsql

below the Database name is always blank
I am trying to get Database Name in a Logon Trigger using EVENTDATA() but its not working and it appears like the EVENTDATA() is not working at all, I am trying to block users who are using excel to query the 'TestDB'. Can someone tell me what I am doing wrong with this code.
CREATE TRIGGER tr_block_excel_users
ON ALL SERVER FOR LOGON
AS
declare #data XML
declare #DatabaseName as varchar(128)
SET #data = EVENTDATA();
set #DataBaseName = #data.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'nvarchar(128)')
BEGIN
IF (select #DatabaseName) = 'TestDB' and ORIGINAL_LOGIN() <> N'xx\xxxxxxxex' AND APP_NAME() LIKE '%Microsoft Office%' OR APP_NAME() LIKE '%EXCEL%'
ROLLBACK;
END
I expected the name of the database using EVENTDATA(), but getting a blank database name,

If you are trying to just get the database and load it into the variable you can try:
SET #DatabBaseName = SELECT DB_NAME()

Related

DB2oC (DB2 on Cloud) : Facing "attempted to modify data but was not defined as MODIFIES SQL DATA" error

I have created very simple function in DB2oC as below, which has one UPDATE sql statement and one SELECT sql statement along with MODIFIES SQL DATA. But still I get the below error, though I have specified MODIFIES SQL DATA. I did GRANT ALL on that TEST table to my user id and also did GRANT EXECUTE ON FUNCTION to my user id on safe side. Can you please help to explain on what could be the issue?
I have simply invoked the function using SELECT statement like below:
SELECT TESTSCHEMA.MAIN_FUNCTION() FROM TABLE(VALUES(1));
SQL Error [38002]: User defined routine "TESTSCHEMA.MAIN_FUNCTION"
(specific name "SQL201211013006981") attempted to modify data but was
not defined as MODIFIES SQL DATA.. SQLCODE=-577, SQLSTATE=38002,
DRIVER=4.27.25
CREATE OR REPLACE FUNCTION MAIN_FUNCTION()
RETURNS VARCHAR(20)
LANGUAGE SQL
MODIFIES SQL DATA
BEGIN
DECLARE val VARCHAR(20);
UPDATE TEST t SET t.CONTENT_TEXT = 'test value' WHERE t.ID = 1;
select CONTENT_TEXT into val from TEST where ID = 1;
return val;
end;
Appreciate your help.
For the modifies SQL data clause , the usage of the function is restricted on Db2-LUW.
These restrictions do not apply for user defined functions that do not modify data.
For your specific example, that UDF will operate when used as the sole expression on the right hand side of an assignment statement in a compound-SQL compiled statemnent.
For example:
create or replace variable my_result varchar(20) default null;
begin
set my_result = main_function();
end#
Consider using stored procedures to modify table contents, instead of user defined functions.
You could avoid using a function, and just use a single "change data statement"
SELECT CONTENT_TEXT
FROM NEW TABLE(
UPDATE TEST t
SET t.CONTENT_TEXT = 'test value'
WHERE t.ID = 1
)

Can we create a trigger (or any object) to catch each login name

Actually I need to find all the users logged into a SQL Server in last month, so that I can delete the users which are not using SQL Server from AD group.
I was not able to find that so now I am trying to create trigger so that after one month I can delete users.
Under the server properties select the Security tab and enable Login auditing for "Both failed and successful logins". The information is then recorded in the SQL Server Logs.
It is also possible to do it via trigger. Something like
CREATE TRIGGER Logon_Audit
ON ALL SERVER
FOR LOGON
AS
BEGIN
declare #acct as nvarchar(max)
set #acct = ORIGINAL_LOGIN()
-- insert #acct into some table
END
I used fully qualified name for table and deleted multiple records
Create Table LoginDetails (iD int identity(1,1),LoginName nvarchar(max) , LoginTime datetime)
Create TRIGGER Logon_Audit
ON ALL SERVER
FOR LOGON
AS
BEGIN
declare #acct as nvarchar(max)
declare #LoginTime as nvarchar(max)
set #acct = ORIGINAL_LOGIN()
set #LoginTime = getdate()
insert into master..LoginDetails
Select top 1 #acct,#LoginTime
delete
from master..LoginDetails
where id not in (
Select max(id)
from LoginDetails
group by LoginName,LoginTime
)
END

How to update column based on column name in postgres?

I've narrowed it down to two possibilities - DynamicSQL and using a case statement.
However, I've failed with both of these.
I simply don't understand dynamicSQL, and how I would use it in my case.
This is my attempt using case statements; one of many failed variations.
SELECT column_name,
CASE WHEN column_name = 'address' THEN (**update statement gives syntax error within here**)
END
FROM information_schema.columns
WHERE table_name = 'employees';
As an overview, I'm using Axios to talk to my Node server, which is making calls to my Heroku database using Massivejs.
Maybe this isn't the way to go - so here's my main problem:
I've ran into troubles because the values I'm planning on using as column names are sent to my server as strings. The exact call that I've been trying to use is
update employees
set $1 = $2
where employee_id = $3;
Once again, I'm passing into those using massive.
I get the error back { error: syntax error at or near "'address'"} because my incoming values are strings. My thought process was that the above statement would allow me to use variables because 'address' is encapsulated by quotes.
But alas, my thought process has failed me.
This seems to be close to answering my question, but I can't seem to figure out what to do in my case if using dynamic SQL.
How to use dynamic column names in an UPDATE or SELECT statement in a function?
Thanks in advance.
I will show you a way to do this by using a function.
First we create the employees table :
CREATE TABLE employees(
id BIGSERIAL PRIMARY KEY,
column1 TEXT,
column2 TEXT
);
Next, we create a function that requires three parameters:
columnName - the name of the column that needs to be updated
columnValue - the new value to which the column needs to be updated
employeeId - the id of the employee that will be updated
By using the format function we generate the update query as a string and use the EXECUTE command to execute the query.
Here is the code of the function.
CREATE OR REPLACE FUNCTION update_columns_on_employee(columnName TEXT, columnValue TEXT, employeeId BIGINT)
RETURNS VOID AS
$$
DECLARE update_statement TEXT := format('UPDATE EMPLOYEES SET %s = ''%s'' WHERE id = %L',columnName, columnValue, employeeId);
BEGIN
EXECUTE update_statement;
end;
$$ LANGUAGE plpgsql;
Now, lets insert some data into the employees table
INSERT INTO employees(column1, column2) VALUES ('column1_start_value','column2_start_value');
So now we currently have an employee with an id value of 1 who has 'column1_start_value' value for the column1, and 'column2_start_value' value for column2.
If we want to update the value of column2 from 'column2_start_value' to 'column2_new_value' all we have to do is execute the following call
SELECT * FROM update_columns_on_employee('column2','column2_new_value',1);

SQL Server 2012 - Permission for access to sys.dm_db_index_usage_stats in Contained Database

In a contained database, how to I grant users read access on this table?
I am trying to create a function to get the date a table was last updated, but when contained users run it, it fails with error 297 ‘The user does not have permission to perform this action.’.
CREATE FUNCTION [MGMT].[GetLastObjectUpdateTime] (#ObjectName NVARCHAR(100))
RETURNS DATETIME
WITH EXECUTE AS OWNER
AS
BEGIN
DECLARE #Result DATETIME
SELECT #result = MAX(last_user_update)
FROM sys.dm_db_index_usage_stats
WHERE OBJECT_ID = OBJECT_ID(#ObjectName)
RETURN #Result
END
(code from : http://blog.sqlauthority.com/2009/05/09/sql-server-find-last-date-time-updated-for-any-table/#comment-684267 )
I would try granting the owner the server permission VIEW SERVER STATE which is needed to use that view.
USE master;
GO
GRANT VIEW SERVER STATE TO [owner login]
GO

the max function requires 1 argument(s)

I wrote this very simple SP in SQL 2008:
Create procedure dbo.GetNextID
(
#TableName nvarchar(50),
#FieldName nvarchar(50)
)
AS
BEGIN
exec('select isnull(max('+#FieldName+'),0)+1 as NewGeneratedID from '+ #TableName);
END
When I execute this procedure in Visual Studio SQL Express and pass a table name and a field name, it works fine. But when I try to add this SP as a query in a QueryTableAdapter in my ADO DataSet, I receive this error before clicking on Finish button:
the max function requires 1 argument(s)
can anyone help me with this?
I guess that VS tries to determine a field list by executing the SP. But as it does not know what to pass to the SP, it uses empty parameters. Now, of course, your select statement fails.
You could try adding the following to your SP:
IF ISNULL(#TableName,'') = '' SET #TableName = '<Name of a test table>';
IF ISNULL(#FieldName,'') = '' SET #FieldName = '<Name of some field>';
Use the names of some field and table that do exist here (for example names that you'd use from your application, too).
Alternatively you could add the following above the exec:
IF (ISNULL(#TableName, '') = '') OR (ISNULL(#FieldName, '') = '')
BEGIN
SELECT -1 AS NewGeneratedId
RETURN 0
END
EDIT
On a side note, I'd like to warn you about concurrency issues that I see coming up from what your code does. If this code is supposed to return a unique ID for a new record in some table, I'd redesign this as follows:
Create a table NumberSeries where each row contains a unique name, a possible range for IDs and the current ID value.
Create a stored procedure that uses UPDATE ... OUTPUT to update the current ID for a number series and retrieve it in one step.
That way you can make sure that creating a new ID is a single operation that does not cause concurrency problems.