Is there something in SQL Server similar to USE (to switch databases) that can control the owner prefix that is used for tables?
For example, we have an application that insists on creating tables "theServiceAccount.TheTableName" ; What we really want is to force it to put the table names under dbo... so "dbo.TheTableName" . We don't have a good way to change the SQL that the application runs (it is vended), other than a hook when it starts up that allows us to run some SQL. So it would be great if we could run a sql at that point which would make subsequent create table (or other operations) default to dbo instead of the service account being used.
I do realize that the create table syntax allows one to specify the owner, but that doesn't seem to be an option at this point. From what I can tell, the SQL this application generates never specifies the owner; it just has the table name in the SQL it runs.
Thanks!
In 2005, by default each user has their own default schema, unless specified.
This should do what you need:
USE databasename
ALTER USER theServiceAccount WITH DEFAULT_SCHEMA = dbo
You can also change this via SSMS by looking at the user properties and changing the default schema
I believe you can do this by creating a user with the default schema you want and then using the EXECUTE AS statement (see http://msdn.microsoft.com/en-us/library/ms181362.aspx)
In your example you could create a user (or use dbo, not advised) called 'specialDBO' that has their default schema set to dbo. Then you have something like this:
USE [myfabdb];
EXECUTE AS USER = 'speicalDBO';
... blah blah blah...
REVERT;
Remember, you can't have the USE statement after the EXECUTE AS statement.
Related
I have two schemas, one contains tables, stored procedures, general data (will call it data schemas from now on). The second schema has nothing but stored procedures inside of it and we'll call this execute schema.
Now the point of the execute schema is so that I can create a user (we'll call this external user), which only has access to this schema and can only execute stored procedure within the execute schema... no select, update, insert, delete nothing (there are no tables anyway in the execute schema) and has zero access to the data schema. This way the user will be very restricted in what it can do.
The point in this is that, when a stored procedure is created with the "execute schema" it elevates the user rights depending on what is required, without actually giving the external user any rights past that execution.
All is well, and I have it executing and get data from the data schema with a test stored procedure. I'm now trying to allow one of the stored procedure in the execute schema to use a user-defined table type, which has been created on the data schema. Due to the user restrictions of not being able to see anything of the data schema it is proving to be a problem.
Now I could recreate the data type or move it to a shared schema... but this is a live old database and ideally I don't want to duplicate types or have to move user-defined stuff every time I wish to allow access to the external user.
So I thought about using Aliases. although when I try to create said alias I get an error:
command:
CREATE TYPE [execute].[udtype1] FROM [data].[udtype1] NOT NULL;
error:
The base type "data.udtype1" is not a valid base type for the alias data type.
While I don't know how to do it, I have noticed that the microsoft documentation creates an utf8string and references it (I'm hoping this means what I want to do, can be done and exists):
CREATE ASSEMBLY utf8string
AUTHORIZATION [dbi]
FROM 0x4D... ;
GO
CREATE TYPE Utf8String
EXTERNAL NAME utf8string.[Microsoft.Samples.SqlServer.utf8string] ;
GO
Does anyone know how to create an alias for a user-defined table, or have an alternative approach.
Quote from comment on the original question:
Alias data types are for scalar data types, you can't create an alias data type of a table type. You'll need to give explicit access to the types on the schema here so that the USER's can declare a parameter of the type. –
User: Larnu
He gave me a couple of keywords which helped with my google search.
https://learn.microsoft.com/en-us/sql/t-sql/statements/grant-type-permissions-transact-sql?view=sql-server-ver15
It is still weird though, as I had allow execution and after giving them rights on the specific stored procedure, I could then remove the rights and it works. Trying to remove the rights first results in the execution failing.
I have a database with mixed case, i.e testDATABASE.
I run(using ODBC) the query use database ""testDATABASE";", then I run the query use schema "PUBLIC",
the query fail with the error:
ERROR: SQL compilation error:
Object does not exist, or operation cannot be performed.
Error Code: 2043
Query = use schema "PUBLIC"
when I run it not via odbc but in the notebook it works fine.
same queries with database that does not contain mixed case works fine.
if i run use schema "testDATABASE"."PUBLIC" it runs OK via ODBC and notebook.
is there a known issue about it? how can i run it with 2 queries in ODBCand make it work?
Thanks.
In your question it looks like your use database command had double double quotes,
but your schema didn't, perhaps that might be the issue.
Overall Suggestions :
When you make object names MiXeD-CaSe it simply makes use of the objects more difficult, so I'd recommend trying to not do mixed case if you can avoid it. You may not be able to avoid this, that's OK, it's just a suggestion.
if you can't avoid it, the only time I'd use the double quotes is when the object name
(in this case, the database name) has mixed case.
In your case, you should be able to run (you may have to double-double quote it in ODBC):
use database "testDATABASE";
and then this - note no double quotes needed because it's not mixed case
use schema PUBLIC;
this document illustrates how you don't need to prefix the schema with the database:
https://docs.snowflake.com/en/sql-reference/sql/use-schema.html
something else I recommend to folks getting started, for each user I like to set all the default context items (role, warehouse, namespace)
ALTER USER rich SET DEFAULT_ROLE = 'RICH_ROLE';
ALTER USER rich SET DEFAULT_WAREHOUSE = 'RICH_WH' ;
ALTER USER rich SET DEFAULT_NAMESPACE = 'RICH_DB.TEST_SCHEMA';
I want to write a query to select a DB and then create a table within that DB.
I have the following query to just create a table, Is there a way to highlight the DB within the command itself?
.create table ABC (
A:string ,
B:string
)
Is there a way to highlight the DB within the command itself?
No - as the command runs in the context of a specific database, you must first make sure you're in the context of the database in which you wish to create the table.
In the web interface, that means 'selecting' the database in the connections panel.
In the API, that means explicitly specifying the database name in the connection string builder (or as part of the REST request parameters), or when calling the method to execute the control command.
I have two schemas on a database named DBO and Switch. I have created this DDL trigger that logs DDL changes on DBO to a table. I then check if the objects affected by the DDL are partitioned or not and if yes I run the same DDL on the other schema Switch. This approach works fine unless the user doesn't specify the schema name in the DDl statement.
I am looking for a way to check the issued DDl for the presence of schema name, and if not present then issue the DDL by default on SWitch schema.
Any ideas on how can I achieve this? I am new to TSQL coding and would appreciate anyone helping me out with this one.
In EVENTDATA available to use in DDL Trigger, there are following fields (among others) available:
<EVENT_INSTANCE>
<DatabaseName>RT-BOOKS</DatabaseName>
<SchemaName>dbo</SchemaName>
<ObjectName>Books_PL$ID</ObjectName>
<TSQLCommand>
<CommandText>
</CommandText>
</TSQLCommand>
</EVENT_INSTANCE>
If <SchemaName> is not enough for you (if understood correctly, you want to check if user explicitly used schema name in a query), then try to parse <CommandText> using <SchemaName> and <ObjectName>.
As the title suggests I am confused as to why some tables in my database fall over if you do something like;
SELECT * FROM [user].[table]
And yet on another tables it works fine.
I am testing some code that will eventually be on a server that cries if you don't use [user].[table] so I would really like to force this on my machine.
Could someone explain why this happens and possible show me how to fix it.
More Info
Here is the message I get when I try and run a query using [user].[table] instead of just [table];
[Microsoft][ODBC SQL Server
Driver][SQL Server]Invalid object name
'usr.tbl'
The "user" bit is the schema a table belongs to
So you can have dbo.table and user.table in the same database.
By default, SELECT * FROM table will usually look for the dbo.table. However, if the login/user has a different default schema then it will look for thatschema.table
To fix it:
You can use ALTER SCHEMA .. TRANSFER.. to fix the current setup
Ongoing, ensure every table reference has the correct schema on CREATE, ALTER, SELECT, whatever
Also see "User-Schema Separation" on MSDN
What you refer to as [user] is actually something called a schema. Every user has a default schema, which means that when you are logged in as that user you can refer to the tables in the default schema without the schema prefix. One way to solve this would to be to make sure that no user has the default schema where the tables are located. Basically you can just make an emptry schema and use that as the default schema for all your users.
Go to YourDatabase->Security->Users and see the properties (by right clicking) to change the default schema for your users.