I want to create a function once and have it be available everywhere on the account.
I don't want to have to specify fully-qualified name in all usages.
And I don't want to create it in every database, and possibly on every schema.
Ideally, it is accessible across the account without specifying database / schema.
For example, suppose I want a case-insensitive contains function available everywhere.
CREATE OR REPLACE FUNCTION udf_icontains(val varchar, search_pattern varchar)
RETURNS BOOLEAN
AS
$$
contains(lower(val), lower(search_pattern))
$$;
It seems I must create it on every database and every schema in order to reference without FQN.
You can create it in a single database and schema, grant public access, and then reference it in queries using its fully-qualified name (db.schema.udf...) from everywhere.
Just create a public database with a name like global or account (we call ours utils) with a public schema called udfs.
You already have a udf_ prefix in the name of your UDF; global.udfs.icontains is not much longer to type than udf_icontains.
CREATE DATABASE IF NOT EXISTS global;
CREATE SCHEMA IF NOT EXISTS global.udfs
GRANT USAGE ON DATABASE global TO ROLE public;
GRANT USAGE ON SCHEMA global.udfs TO ROLE public;
GRANT USAGE ON FUTURE FUNCTIONS IN SCHEMA global.udfs TO ROLE public;
GRANT USAGE ON ALL FUNCTIONS IN SCHEMA global.udfs TO ROLE public;
Related
I'm interested in finding a method where a system wide variable can be written onto the Snowflake Account, and used in a view so that users can see the underlying DDL, but not know the value used in a particular function.
At the moment this is done by making these a "Secure" View, but that limits almost everyone from seeing the underlying DDL (which would be helpful to our users and admins).
I'm wondering if there is a way to set a System Wide Variable, and use that in the DDL.
Example:
SET SYSTEM VARIABLE variable_name = 'some_value';
CREATE VIEW catalog.schema.tablename AS
SELECT TRANSLATE(COLUMN_NAME, '0123456789', variable_name) AS NEW_COLUMN_NAME
FROM <FULL SOURCE TABLE NAME>
WHERE <WHATEVER CONDITIONS APPLY>;
I have found setting variables on a session, and I know I can see / change Account Parameters. But can I create something like Account Variables?
Function has two privileges on it - OWNERSHIP and USAGE. If you don't give either of these function privileges to the viewer of the view, but you give the viewer SELECT privileges on the view, they will be able to see the DDL of the view, but won't be able to see the details of the UDF. Then you can store values in your UDF that you don't want other people seeing. I'll post code for this in just a second.
--Something like this to test it out from scratch. You must have accountadmin for this to work:
--use role accountadmin:
--create a database called demo_db;
--create a role called owner_demo_db and grant it usage, monitor, and create schema; also give it usage on a warehouse;
--create a user called demo_db_user. give them ownership on demo_db;
--create a role called reader_demo_db;
--assign the "reader" and the "owner" role to demo_db_user;
--as the owner_demo_db role, create the following:
use role owner_demo_db;
--The role owner_demo_db will own this function
create function pi_udf()
returns float
as '3.141592654::FLOAT'
;
--The role owner_demo_db will own this view
create view MyView as
select 'some_value' AS someval
, pi_udf() pi_val;
--Because owner_demo_db owns the view, they can grant select to the reader role to the view
grant select on view demo_db.demo_schema.MyView to reader_demo_db;
--Show functions and views and you'll be able to see both.
show functions;
show views;
--Show functions and views as reader_demo_db, and you'll only be able to see DDL for the view b/c you don't have a privilege on the function
use role reader_demo_db;
show functions;
show views;
When installing a new db, it is a best practice to create a new user and a new tablespace, because creating tables shouldn't be done with SYS/SYSTEM or/and on the tablespace "SYSTEM".
So I created the user "alex" and the tablespace "alexData" with the following commands:
CREATE TABLESPACE alexData datafile 'C:/oraclexe/alexData.dbf'
size 100M;
ALTER USER alex QUOTA UNLIMITED ON alexData;
ALTER USER alex QUOTA 0 ON SYSTEM;
I want to accomplish that the user "alex" is only able to save his data in the "alexData" tablespace.
Why? Because when he wants to access a table he shouldn't always have to mention the tablespace "alexData".
otherwise he would always need to mention it like:
SELECT *
FROM alexData.table
but I want that he always is JUST in that tablespace so he doesn't need to mention it:
SELECT *
FROM table;
Is this possible?
First of all , Consequence of what #Mat told, you can not use like
SELECT * FROM alexData.table_ but SELECT * FROM alex.table_, since a table may be prefixed with a schema name. As you may notice, you can not use table,which is a keyword for oracle, as table name, so i've used table_ instead.
When you create user, the object is automatically created inside that tablespace. As an example, when create table ... statement issued, there's no need to mention about the tablespace provided that you create or alter your user with DEFAULT TABLESPACE phrase:
CREATE USER alex IDENTIFIED BY alex321
DEFAULT TABLESPACE alexData
TEMPORARY TABLESPACE alexTempData;
OR
ALTER USER alex IDENTIFIED BY alex321
DEFAULT TABLESPACE alexData;
You cannot create triggers on a table owned by SYS, or SYSTEM see:
Why cannot I create triggers on objects owned by SYS?
If the table on which you wish to create a trigger is a table which you have created, it should live on the ALEX schema. This schema should have privileges to create triggers on tables created in the same schema. As previously mentioned in the comments, you should revoke the CREATE ANY TABLE privilege from the ALEX schema, as this user should only be able to create tables on their own schema.
I have two schemas, schema_ui and schema_logic.
schema_logic is for privileged users and I will define my tables in this schema. schema_ui is for restricted users with limited functionality, so they cannot access the tables in schema_logic.
I create a sp_ReadTable1 in schema_ui and this stored procedure reads from Table1 in schema_logic. user1 has restricted permission and can only access, schema_ui. Now user1 has access to sp_ReadTable1 but can he actually execute it, as the stored procedure reads from table1?
So, something like C# public method, which returns private members...
We have a function that is written in t-sql and we converted it for oracle. But I cannot find equivalent of Authorization keyword for oracle.
GO
ALTER AUTHORIZATION ON [DOCSADM].[Cbinary] TO SCHEMA OWNER
GO
GRANT EXECUTE ON [DOCSADM].[Cbinary] TO [public] AS [DOCSADM]
GO
DOCSAdm is a user and CBinary is myfunction name. How to convert these sql code for oracle?
The ALTER AUTHORIZATION transfers ownership of an object to another user.
As Oracle handles Users and Schemas a bit differently than SQL Server, there is no equivalent. In general, an object like your function Cbinary is owned by the schema it is located in.
Moving an object to another user/schema in Oracle is done in the way that you use the CREATE-Script like you would use it normally, but just add the new schema-name in front of the object-name, like this:
create function newschema.cbinary return varchar2 as
begin
-- your code here
end cbinary;
I have a database FooDb with a schema BarSchema that contains a table Tbl (i.e. FooDb.BarSchema.Tbl)
I am also logged in as a user with BarSchema as default.
This query works fine
SELECT * FROM FooDb..Tbl
I also have a synonym for this table in another db
CREATE SYNONYM TblSynonym FOR FooDb..Tbl
But now I get an error "Invalid object name 'FooDb..Tbl'" when executing
SELECT * FROM TblSynonym
If i change the synonym to
CREATE SYNONYM TblSynonym FOR FooDb.BarSchema.Tbl
it works fine.
Why doesn't the default schema work in synonyms?
(The background is that I'm consoldating data from several databases which all got same table names but different schema names. It would be a lot easier if I could set the default schema for each database on the user and then ignore it everywhere in the script)
The documentation suggests the db..tbl syntax should work:
schema_name_2 Is the name of the
schema of the base object. If
schema_name is not specified the
default schema of the current user is
used.
This works for me in SQL Server 2008:
create synonym TestSynonym for TestDB..TestTable
One cause might be that the default schema is associated with the user, not the database. Check if your user has an unexpected default schema? In my SSMS, that setting is located under Database -> Security -> Users -> Properties.