SQL Server - Display the username in a column - sql

We have a SQL Server 2012 database that 4 developers use, lets call them, user1, user2, user3, user4.
I want to create a column in one of the tables lets call the column User_Input, this column needs to show the username of the developer who insert any data, is this possible? For example if user2 inserted a new record, the column User_Input should display user2.
Please let me know if SQL Server does not support that, and if there is any other solution cause I searched the ## functions for SQL Server and non of them seems to get the username.

SYSTEM_USER function will return the login name of the user.
You can test it out with this statement:
SELECT SYSTEM_USER
The MSDN documentation for SYSTEM_USER states:
You can use the SYSTEM_USER function with DEFAULT constraints in the
CREATE TABLE and ALTER TABLE statements. You can also use it as any
standard function.
Here is a quick example of how to create a table with DEFAULT constraint that inserts the SYSTEM_USER into the User_Input column.
CREATE TABLE MyTable
(
ID int,
Value varchar(30),
User_Input varchar(200) DEFAULT SYSTEM_USER
)

I believe this is what you're looking for.
SELECT SYSTEM_USER
You can add this to inserts/updates as needed.
CURRENT_USER provides the schema, not the login associated with the transaction.

Related

Oracle SQL alter table add column with current user name

It was a 2 part question and I got the timestamp correctly.
I'm on 12C and trying to do something like:
ALTER TABLE customers
ADD modified_by (USER FROM DUAL);
Basically just columns in a table that show who modified the table and at what time they did so.
I also tried
ALTER TABLE customers
ADD last_modified TIMESTAMP;
ALTER TABLE customers
ADD modified_by USER;
and other combinations of keywords that I found on this site and other sites but none of them work.
We only learned dual in class but I'm looking for any way to do these.
Edit:
I now understand what was taught to me by the user with almost 1 million points.
Still unsure how to do the username.
Read this:
https://docs.oracle.com/cd/B19306_01/server.102/b14237/statviews_2114.htm#REFRN20302
and tried:
ALTER TABLE customers
ADD modified_by USERNAME;
doesn't work get invalid datatype.
Then saw this: https://www.techonthenet.com/oracle/questions/find_users.php
and tried:
ALTER TABLE customers
ADD modified_by USERNAME FROM DBA_USERS;
but getting invalid alter table option. SQL is hard.
After you edited the question, it seems that you are somewhat closer to what you want. This:
ALTER TABLE customers ADD modified_by VARCHAR2(30);
^^^^^^^^^^^^
datatype goes here, not what you'd like
to put into this column
Then, during inserts or updates of that table, you'd put USER in there, e.g.
insert into customers (id, modified_by) values (100, USER);
Or, probably even better, set it to be default, as #a_horse_with_no_name suggested:
ALTER TABLE customers ADD modified_by VARCHAR2(30) DEFAULT USER;
so - if you don't explicitly put anything into that column, it'll be populated with the USER function's value.
If you read through the Oracle documentation on virtual columns, you will find this:
Functions in expressions must be deterministic at the time of table creation, but can subsequently be recompiled and made non-deterministic
A deterministic function is one that returns the same value when it is passed the same arguments. The expressions that you are using contain non-deterministic functions. Hence, they are not allowed.
The error that I get when I try this is:
ORA-54002: only pure functions can be specified in a virtual column expression
For some unknown reason, Oracle equates "pure" with "deterministic" in the error message. But this is saying that the function needs to be deterministic.

How to list schemas of a specific database in Informix using SQL?

What is the query to get a list of schemas names in a specific database in Informix?
Schemas are not commonly used in Informix databases and have very little trackability within a database. The CREATE SCHEMA notation is supported because it was part of SQL-89. The AUTHORIZATION clause is used to determine the (default) 'owner' of the objects created with the CREATE SCHEMA statement. There is nothing to stop a single user running the CREATE SCHEMA statement multiple times, either consecutively or at widely different times (in any given database within an Informix instance).
CREATE SCHEMA AUTHORIZATION "pokemon"
CREATE TABLE gizmo (s SERIAL NOT NULL PRIMARY KEY, v VARCHAR(20) NOT NULL)
CREATE TABLE widget(t SERIAL NOT NULL PRIMARY KEY, d DATETIME YEAR TO SECOND NOT NULL)
;
CREATE SCHEMA AUTHORIZATION "pokemon"
CREATE TABLE object (u SERIAL NOT NULL PRIMARY KEY, i INTEGER NOT NULL)
CREATE TABLE "pikachu".complain (C SERIAL NOT NULL PRIMARY KEY, v VARCHAR(255) NOT NULL)
;
After the CREATE SCHEMA statement executes, there is no way of tracking that either pair of these tables were created together as part of the same schema; there's no way to know that "pikachu".complain was part of a CREATE SCHEMA statement executed on behalf of "pokemon". There is no DROP SCHEMA statement that would necessitate such support.
A schema belongs to a user. You can list all available users from the sysusers system catalog :
SELECT username FROM "informix".sysusers;
Since only DBAs and Resource privilieges allow a user to issue a CREATE SCHEMA statement, we could restrict the query like :
SELECT username FROM "informix".sysusers WHERE usertype IN ('D', 'R');
Another solution is to list only users that actually have created tables ; for that, you can query the systables system catalog and list distinct owners.
SELECT DISTINCT owner FROM FROM "informix".systables
As commented by #JonathanLeffler, a user could have been granted RESOURCE privileges and have created a table, and then be 'demoted' to CONNECT privileges. The user would still own the table. Hence the second solution is the most accurate.

Most efficient way to sustain a maximum number of entries in SQL Server database table

I was wondering, what is the most efficient way of doing the following?
I'm trying to implement some sort of an auditing system where each logon to my page will be stored in a database. I use SQL Server 2005 database. The table that stores the auditing data obviously cannot grow without an upper limit. So, say, it should have a maximum of 1000 entries and then any older entries must be deleted when new ones are inserted. The question is how do you do this in a most efficient way -- do I need to add any special columns, like, say an ordinal entry number for easier clean-up?
EDIT:
Say, if the structure of my table is (pseudo code):
`id` BIGINT autoincrement
`date` DATETIME
`data1` NVARCHAR(256)
`data2` INT
How would you write this cleanup procedure?
As Tony mentioned, use dates to identify the inserts. In addition, use a clustered index on the date field, so that inserts are always at the end of the table and it is easy and efficient to scan through and delete the old rows.
If you use a number, something like this should work:
DELETE FROM myTable WHERE someField < (SELECT MAX(someField) - 1000 FROM myTable)
For a date, deleting everything older than one day would be something like:
DELETE FROM myTable WHERE someField < DateAdd('d', -1, getdate())
Do it by date not number. Have a look at your stats, see how many days 1000 is / will be. Delete anything older than that. Auditing is never particularly efficient, but if you have loads of data that doesn't help you that's very inefficient....
If I understand your needs, this should work. I've tested it on SQL 2008R2, but I can not see any reason why it would not work on SQL Server 2005.
Use a logon trigger to insert a row into your audit table.
Create an AFTER INSERT trigger on your audit table that deletes the row with MIN(ID).
Here's some code to play with:
/* Create audit table */
CREATE TABLE ServerLogonHistory
(SystemUser VARCHAR(512),
ID BIGINT,
DBUser VARCHAR(512),
SPID INT,
LogonTime DATETIME)
GO
/* Create Logon Trigger */
CREATE TRIGGER Tr_ServerLogon
ON ALL SERVER FOR LOGON
AS
BEGIN
INSERT INTO TestDB.dbo.ServerLogonHistory
SELECT SYSTEM_USER, MAX(ID)+1 , USER,##SPID,GETDATE()
FROM TestDB.dbo.ServerLogonHistory;
END
GO
/* Create the cleanup trigger */
CREATE TRIGGER AfterLogin
ON TestDB.dbo.ServerLogonHistory
AFTER INSERT
AS
DELETE
FROM TestDB.dbo.ServerLogonHistory
WHERE ID =
(SELECT MIN(ID) FROM TestDB.dbo.ServerLogonHistory);
GO;
A word of warning. If you create an invalid logon trigger, you'll not be able to logon to the database. But don't panic! It's all part of learning. You'll be able to use 'sqlcmd' to drop the bad trigger.
I did try to delete the row with the min ID in the logon trigger, but I was not able to get that to work.
Is the "ID" column a Identity column with step 1?
after you insert one row
delete column where id<IDENTITY_CURRENT(YOUR_TABLE)-1000

SQL Server 2008 - permission denied in database 'master'

I am new to SQL Server and I wanted to create my first table there.
create table Employee
(
ID smallint not null
)
I use SQL Server 2008 R2 and Windows Authentication.
when I execute , it says :
CREATE TABLE permission denied in database 'master'.
Thanks!
Seems you're trying to create the table in master database where you may not have permission to create table. However, to create your target database please follow below steps:
a. At your SQLQuery editor choose your target database (Available Database drop down list) and execute your sql query.
Or
b. Try with below statement:
USE YourTargetDatabaseName
GO
CREATE TABLE Employee ( ID SMALLINT NOT NULL)
GO
I don't think you want to create a table in the master database.
Did you create a new database first? If so, use this:
USE [MyNewDatabaseName]
GO
create table Employee ( ID smallint not null )
GO

How do I make one user see a different table with same name

Goal: When everybody else does SELECT * FROM mytable they see one version of the table. But when a specific user does SELECT * FROM mytable they see another version of the table.
I think I'm like halfway there with creating a new role and putting the single user in it. Then creating a copy of the default table with SELECT * INTO newrole.mytable FROM dbo.mytable. But when the user does SELECT * FROM mytable they still see the dbo.mytable. How do I get them to default to the newrole.mytable? I still need them to see all the other dbo tables just not this one.
Create a new schema, and a duplicate table (or view onto dbo.table if that's what you want) in it - eg., otheruser.table. Then, set the user's login to default to that schema:
USE atest
GO
CREATE ROLE [arole]
GO
CREATE SCHEMA [aschema] AUTHORIZATION [arole]
GO
CREATE USER [auser] FOR LOGIN [modify_user] WITH DEFAULT_SCHEMA = aschema
GO
EXEC sp_addrolemember 'arole', 'auser'
GO
CREATE TABLE dbo.atable ( col1 int )
GO
CREATE TABLE aschema.atable (col2 varchar(10))
GO
INSERT INTO dbo.atable( col1 ) VALUES( 1 )
GO
INSERT INTO aschema.atable( col2 ) VALUES( 'One' )
GO
PRINT 'dbo'
SELECT * FROM atable
GO
EXECUTE AS USER = 'auser'
GO
PRINT 'aschema'
SELECT * FROM atable
GO
REVERT
GO
I don't know if this may help but you may be able to make a view of a different table with the same name, here is an excerpt from http://www.w3schools.com/SQl/sql_view.asp:
In SQL, a view is a virtual table based on the result-set of an SQL statement.
A view contains rows and columns, just like a real table. The fields in a view are fields from one or more real tables in the database.
You can add SQL functions, WHERE, and JOIN statements to a view and present the data as if the data were coming from one single table.
I use Postgres primarily, so YMMV, but in postgres you need to
1) Create the new schema, preferably owned by the new role, and put the table in it
2) Set the search_path variable to include that schema BEFORE the other one.
Hope it helps.
This is a very bad idea. I'm not sure why people try all these crazy methods to improve security but it's just plain counter productive.
Ultimately every security system comes down to some line like the following if(User.HasAccessTo(object)). In fact, if you've designed a well thought out security system that's almost exactly how it should work. The more disjointed your authentication checks, the more likely you'll make a mistake. If only some users have access to certain record information you should add a flag to those records and verify access based on that.