Different Database Directory Per Database - database

I want to set an default location per database
Example:
database1 - is on /var/www/html/database1
database2 - is on /var/www/html/database2
Locations stated are only examples I want to store it elsewhere like another partition of an Hard Drive.
Is this possible?
For PostgreSQL?
Thanks!

Use tablespaces:
create tablespace db1_space
owner = db1_owner
location = '/var/www/html/database1';
create tablespace db2_space
owner = db2_owner
location = '/var/www/html/database2';
Then create the databases with the appropriate tablespace:
create database db1
owner = db1_owner
tablespace = db1_space;
create database db2
owner = db2_owner
tablespace = db2_space;
Unrelated, but: I would never put a tablespace below /var/www

data_directory is defined per cluster and so is same for all databases.
what you probably want instead is creating a tablespace in a different location and storing all data in one DB in that tablespace...

Related

Docker / Oracle Database / Volume Persistence / Create Table space

I am building a Dev Docker environment and I have to set up an Oracle 19c database.
I have been successful... but not at 100%.
Everything is running correctly, I can create a tablespace, a user/schema, create a table, insert data, access via NodeJs the data too until I restart the container.
In all the tutorials, it is shown to mount a volume pointing to /opt/oracle/oradata
volumes:
- ./database/OracleDB/oradata:/opt/oracle/oradata
But the tablespace are created by default in the /opt/oracle/product/19c/dbhome_1/dbs
I tried to add a volume pointing to that directory
volumes:
- ./database/OracleDB/oradata:/opt/oracle/oradata
- ./database/OracleDB/dbs:/opt/oracle/product/19c/dbhome_1/dbs/
But I receive the following error Error response from daemon: path /home/myusr/docker-base/database/OracleDB/dbs is mounted on / but it is not a shared mount.
Anybody has already faced this issue and found a solution?
I continue of course to search to a solution ;)
System Information
Windows 10 Professionnal with WSL2
Docker version 20.10.8, build 3967b7d
Oracle Database 19c
UPDATE 1
Based on Roberto Comments. Unfortunately, it is not working.
UPDATE 2
I tried the following
CREATE TABLESPACE tbs1_test DATAFILE '/opt/oracle/oradata/tbs1_test' SIZE 100 M AUTOEXTEND ON NEXT 100 M MAXSIZE 10 G;
and it as created the file in the desired location
When you don't change the value of db_create_file_dest, Oracle will use it as default destination for datafiles. In your case, when you executed your create tablespace command, the datafile was created in the default location. That is why it does not appear on your desired directory.
1.Connect as sysdba to the database
2.Execute
SQL> alter system set db_create_file_dest = '/opt/oracle/oradata/ORCLCDB' scope=both;
3.As you have a volume already in the above directory, remove the other volume specification, as it is already shared under /
4.Remove the tablespace and create it back again ( if it is empty )
SQL> DROP TABLESPACE tbs1_test including contents and datafiles;
SQL> CREATE TABLESPACE tbs1_test DATAFILE 'tbs1_test' SIZE 100 M AUTOEXTEND ON NEXT 100 M MAXSIZE 10 G;
5.Verify that the datafile now is in the right volume
SQL> select file_id, file_name from dba_data_files where tablespace_name = 'TBS1_TEST' ;
If you want to dig more in how to create specific volumes inside a docker image, check this post in Stackoverflow, it is one of the best IMHO
How to mount host volumes into docker containers in Dockerfile during build

In the tutorial "Tutorial: Bulk Loading from a local file system using copy" what is the difference between my_stage and my_table permissions?

I started to go through the first tutorial for how to load data into Snowflake from a local file.
This is what I have set up so far:
CREATE WAREHOUSE mywh;
CREATE DATABASE Mydb;
Use Database mydb;
CREATE ROLE ANALYST;
grant usage on database mydb to role sysadmin;
grant usage on database mydb to role analyst;
grant usage, create file format, create stage, create table on schema mydb.public to role analyst;
grant operate, usage on warehouse mywh to role analyst;
//tutorial 1 loading data
CREATE FILE FORMAT mycsvformat
TYPE = "CSV"
FIELD_DELIMITER= ','
SKIP_HEADER = 1;
CREATE FILE FORMAT myjsonformat
TYPE="JSON"
STRIP_OUTER_ARRAY = true;
//create stage
CREATE OR REPLACE STAGE my_stage
FILE_FORMAT = mycsvformat;
//Use snowsql for this and make sure that the role, db, and warehouse are seelcted: put file:///data/data.csv #my_stage;
// put file on stage
PUT file://contacts.csv #my
List #~;
list #%mytable;
Then in my active Snowsql when I run:
Put file:///Users/<user>/Documents/data/data.csv #my_table;
I have confirmed I am in the correct role Accountadmin:
002003 (02000): SQL compilation error:
Stage 'MYDB.PUBLIC.MY_TABLE' does not exist or not authorized.
So then I try to create the table in Snowsql and am successful:
create or replace table my_table(id varchar, link varchar, stuff string);
I still run into this error after I run:
Put file:///Users/<>/Documents/data/data.csv #my_table;
002003 (02000): SQL compilation error:
Stage 'MYDB.PUBLIC.MY_TABLE' does not exist or not authorized.
What is the difference between putting a file to a my_table and a my_stage in this scenario? Thanks for your help!
EDIT:
CREATE OR REPLACE TABLE myjsontable(json variant);
COPY INTO myjsontable
FROM #my_stage/random.json.gz
FILE_FORMAT = (TYPE= 'JSON')
ON_ERROR = 'skip_file';
CREATE OR REPLACE TABLE save_copy_errors AS SELECT * FROM TABLE(VALIDATE(myjsontable, JOB_ID=>'enterid'));
SELECT * FROM SAVE_COPY_ERRORS;
//error for random: Error parsing JSON: invalid character outside of a string: '\\'
//no error for generated
SELECT * FROM Myjsontable;
REMOVE #My_stage pattern = '.*.csv.gz';
REMOVE #My_stage pattern = '.*.json.gz';
//yay your are done!
The put command copies the file from your local drive to the stage. You should do the put to the stage, not that table.
put file:///Users/<>/Documents/data/data.csv #my_stage;
The copy command loads it from the stage.
But in document its mention like it gets created by default for every stage
Each table has a Snowflake stage allocated to it by default for storing files. This stage is a convenient option if your files need to be accessible to multiple users and only need to be copied into a single table.
Table stages have the following characteristics and limitations:
Table stages have the same name as the table; e.g. a table named mytable has a stage referenced as #%mytable
in this case without creating stage its should load into default Snowflake stage allocated

What is the difference between user postgres and a superuser?

I created a new superuser just so that this user can run COPY command.
Note that a non-superuser cannot run a copy command.
I need this user due to a backup application, and that application requires to run COPY command
But all the restrictions that I specified does not take effect (see below).
What is the difference between user postgres and a superuser?
And is there a better way to achieve what I want? I looked into a function with security definer as postgres ... that seems a lot of work for multiple tables.
DROP ROLE IF EXISTS mynewuser;
CREATE ROLE mynewuser PASSWORD 'somepassword' SUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT LOGIN;
-- ISSUE: the user can still CREATEDB, CREATEROLE
REVOKE UPDATE,DELETE,TRUNCATE ON ALL TABLES IN SCHEMA public, schema1, schema2, schema3 FROM mynewuser;
-- ISSUE: the user can still UPDATE, DELETE, TRUNCATE
REVOKE CREATE ON DATABASE ip2_sync_master FROM mynewuser;
-- ISSUE: the user can still create table;
You are describing a situation where a user can write files to the server where the database runs but is not a superuser. While not impossible, it's definitely abnormal. I would be very selective about who I allow to access my DB server.
That said, if this is the situation, I'd create a function to load the table (using copy), owned by the postgres user and grant the user rights to execute the function. You can pass the filename as a parameter.
If you want to get fancy, you can create a table of users and tables to define what users can upload to what tables and have the table name as a parameter also.
It's pretty outside of the norm, but it's an idea.
Here's a basic example:
CREATE OR REPLACE FUNCTION load_table(TABLENAME text, FILENAME text)
RETURNS character varying AS
$BODY$
DECLARE
can_upload integer;
BEGIN
select count (*)
into can_upload
from upload_permissions p
where p.user_name = current_user and p.table_name = TABLENAME;
if can_upload = 0 then
return 'Permission denied';
end if;
execute 'copy ' || TABLENAME ||
' from ''' || FILENAME || '''' ||
' csv';
return '';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
COPY with option other than writing to STDOUT and reading from STDIN is only allowed for database superusers role since it allows reading or writing any file that the server has privileges to access.
\copy is a psql client command which serves the same functionality as COPY but is not server-sided, so only local files can be processed - meaning it invokes COPY but ... FROM STDIN / ... TO STDOUT, so that files on a server are not "touched".
You can not revoke specific rights from a superuser. I'm quoting docs on this one:
Docs: Access DB
Being a superuser means that you are not subject to access controls.
Docs: CREATE ROLE
"superuser", who can override all access restrictions within the database. Superuser status is dangerous and should be used only when really needed.

restore database from backup

I have a database called IND_Master which I have backed up in a file named "IND_Master.bak".
I would like to restore this into another database called 'IND_test" so that they are identical. both the data and structure needs to be identical.
Can someone either give me the script or tell me how to do this from sql server..even if it means creating another IND_master and changing the name to IND_test.
The following script will restore your backup file to a new database called IND_test and rename the logical file names accordingly. Obviously you'll need to alter the paths though.
USE [master]
RESTORE DATABASE [IND_test]
FROM DISK = N'C:\SQL\Backups\IND_Master.bak' WITH FILE = 1,
MOVE N'IND_master' TO N'C:\SQL\Data\IND_test.mdf',
MOVE N'IND_master_log' TO N'C:\SQL\Logs\IND_test_log.ldf'
GO
ALTER DATABASE [IND_test]
MODIFY FILE (NAME = 'IND_master', NEWNAME = 'IND_test')
GO
ALTER DATABASE [IND_test]
MODIFY FILE (NAME = 'IND_master_log', NEWNAME = 'IND_test_log')
GO

PhpMyAdmin does not list a database I have access to

When I start phpMyAdmin, it does not list a database I have access too.
I know that the db exists and that I have access too, because its is the database used by one of my Joomla site.
I picked up the credential from my joomla configuration to the config.inc.php file.
Here is the file:
$cfg['Servers'][$i]['verbose'] = 'SQL9_MODULES';
$cfg['Servers'][$i]['host'] = 'sql9.modules';
$cfg['Servers'][$i]['port'] = '';
$cfg['Servers'][$i]['socket'] = '';
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['extension'] = 'mysql';
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['user'] = 'xxxx';
$cfg['Servers'][$i]['password'] = 'yyy';
$cfg['DefaultLang'] = 'en';
$cfg['ServerDefault'] = 1;
$cfg['UploadDir'] = '';
$cfg['SaveDir'] = '';
I tried as mentionned in other post this command :
SELECT SCHEMA_NAME AS `Database` FROM INFORMATION_SCHEMA.SCHEMATA;
The results is empty.
I have also started the "Synchronize" function from my joomla database to my joomla database and pma found all the tables !!!!
The I tried to write some selects directly on the tables but I got a
#1046 - No database selected
Last remark, this is shared hosting, so I cannot connect as root to grand me some extra privileges !!
Thanks for your help
MySQL version : 5.1.66-0+squeeze1-log - (Debian)
phpMyAdmin version : 3.5.3
Update:
SHOW GRANTS FOR CURRENT_USER
gives
GRANT USAGE ON *.* TO 'xxxx'#'%' IDENTIFIED BY PASSWORD '*****************'
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE ON `xxxx`.* TO 'xxxx'#'%'
Any missing grants ?
Got answer from my ISP support. Needed to add the following line in the configuration:
$cfg['Servers'][$i]['only_db'] = 'my-database';
Now it works.

Resources