LOB storage parameter query - oracle11g

This is for Oracle 11
I created a table by running a script like this:
CREATE TABLE "SYSTEM"."Table12" (
"Column1" CLOB
)
PCTFREE 0
PCTUSED 0
LOGGING
NOCOMPRESS
LOB("Column1") STORE AS (TABLESPACE "TEMP"
STORAGE (INITIAL 65537)
ENABLE STORAGE IN ROW
CHUNK 8193
PCTVERSION 11
CACHE
LOGGING);
Now, I am trying to run queries to obtain the values of storage parameters of Column1.
I started with the tablespace name and I used
SELECT TABLESPACE_NAME FROM ALL_LOBS WHERE COLUMN_NAME = 'Column1'
I was able to get the name successfully. I tried to obtain the value of "INITIAL" which is 65537; however, can't seem to find the right query to get it.
Please kindly advise.
Samir

Related

How to put an update in a API function

as a rule, it's better to hide the single-row fetches inside a function, so instead of:
BEGIN
SELECT name
INTO l_name
FROM mytable
WHERE primary_key = id_primary_key;
it would be better to develop a
PACKAGE mypackage
IS
FUNCTION fnc_name (id_primary_key IN mytable.primary_key%TYPE)
RETURN mytable.name%TYPE;
and executing
BEGIN
l_name := mypackage.fnc_name (id_primary_key);
But what about updating?
I mean, if I decide to develop the same solution for updating but in that case every time I need to update only few columns of the table, how would you develop such an API?
Oracle version 10g
Thanks!
Mark
You are starting to develop a "table API" or "TAPI". These are problematic, for the reason you have mentioned: if the TAPI's update procedure updates all 20 columns of the table from 20 parameters, but in a particular case you only need to update 3 columns, how should you call it? One way is to simply have to pass all 20 values even though you are not changing most of them. Another is to give each parameter a "funny" default like CHR(0) and have the API update be like:
UPDATE mytable
SET column1 = CASE WHEN p_column1 = CHR(0) THEN column1 ELSE p_column1 END,
...
A different (I'd say better) approach is the "Transaction API" or XAPI. Here you build a separate procedure for each business transaction that might need to update the table. For example:
PROCEDURE terminate_employee
( p_empid INTEGER
, p_termination_date DATE
, p_termination_reason VARCHAR2
);
This procedure will use a simple SQL update statement to update the 3 columns that need to be updated when terminating an employee.
Some would say SQL is an API to the database!

Missing privilege for "insert [...] on duplicate key update" statement, but enough for "insert" and "update" seperatly

I tried to reduce the rights a database user has to the minimum needed. Doing so I noticed the following situation:
I have a database test and a user user with the following privileges:
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user'#'%';
GRANT SELECT, INSERT ON test.test TO 'user'#'%';
GRANT UPDATE (y) ON test.test TO 'user'#'%';
The test table (InnoDB) is defined as
create table test
(
x int null,
y int null
);
create unique index test_x_uindex on test (x);
I can run insert and update queries like
INSERT INTO test (x,y) VALUES (1,1), (2,2);
UPDATE test SET y = 3 WHERE x = 1;
But running
INSERT INTO test (x,y) VALUES (2,4) ON DUPLICATE KEY UPDATE y = VALUES(y);
results in
ERROR 1143 (42000): UPDATE command denied to user 'sap'#'localhost' for column 'x' in table 'test'
The same happens if the statement wouldn't actually update something but just insert a new row.
This seems a little bit odd. I couldn't find a directly related bug report. Just something older for MySQL (Is closed but someone said that it is not actually fixed. I did not test it.). In the documentation of MySQL 8.0 the mention that update privileges are only needed for changed columns. The MariaDB documentation does not mention any privilege requirements.
Do I miss something?
This was all tested on MariaDB 10.2.16.

Insert Query executing on local DB but not on server

I'm facing a strange error. I have a 5.5.5-10.1.20-MariaDB install on my local mac (brew) and a 5.5.52-MariaDB on my prod server (centos7). My local DB content is a copy from my server DB. I've executed this query on local:
## CREATE DIRECT RELATION BETWEEN JOURNAL AND PUBLICATION
INSERT INTO journal_publication (journal_id, `publication_id`) (
select issues.journal_id as journal_id, publications.id as publication_id from issues
join publications on issues.id = publications.`issue_id`
where publications.id Not In (select distinct publication_id from journal_publication)
);
It works fine and takes only less than a second to execute.
Now when I try the exact same query on my prod server, the query is never ending and takes all CPUs. Moreover, I've tried to EXPLAIN the query, it works fine on my local:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY issues index PRIMARY issues_journal_id_foreign 5 NULL 70993 Using index; Using temporary
1 PRIMARY publications ref publications_issue_id_foreign publications_issue_id_foreign 5 pubpeer.issues.id 1 Using where; Using index
2 MATERIALIZED journal_publication index NULL PRIMARY 8 NULL 143926 Using index
Whereas the same query on my Prod returns an error:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'INSERT INTO journal_publication (journal_id, `publication_id`)
(select issues.j' at line 2
Again, the content of the two DBs are identical, primary keys and indexes are set equally. For the record, when I try and execute this query:
select issues.journal_id as journal_id, publications.id as publication_id from issues
join publications on issues.id = publications.`issue_id`
where publications.id Not In (select distinct publication_id from journal_publication;
either on local or prod takes only a second.
Have you got any clue or process I could follow to help me understand these differences?
Thanks.
Xavier
MariaDB server versions < 10.0 only support EXPLAIN SELECT
MariaDB server versions >= 10.0 support additionally EXPLAIN
UPDATE, EXPLAIN INSERT and EXPLAIN DELETE
Please note that the version string 5.5.5-10.1.20-MariaDB means MariaDB 10.1.20, the 5.5.5 prefix is required since MySQL replication would break, since it supports only 1 digit numbers for the major version.
See also EXPLAIN UDATE/INSERT/DELETE in MySQL and MariaDB

sqlite: insert or update a row, performance issue

sqlite table:
CREATE TABLE IF NOT EXISTS INFO
(
uri TEXT PRIMARY KEY,
cap INTEGER,
/* some other columns */
uid TEXT
);
INFO table has 5K+ rows and is run on a low power device (comparable to a 3 year old mobile phone).
I have this task: insert new URI with some values into INFO table, however, if URI is already present, then I need to update uid text field by appending extra text to it if the extra text to be appended isn't found within existing uid string; all other fields should remain unchanged.
As an example: INFO already has uri="http://example.com" with this uid string: "|123||abc||xxx|".
I need to add uri="http://example.com" and uid="|abc|". Since "|abc|" is a substring within existing field for the uri, then nothing should be updated. In any case, remaining fields shouldn't be updated
To get it done I have these options:
build some sql query (if it's possible to do something like that with sqlite in one sql statement),
Do everything manually in two steps: a) retrieve row for uid, do all processing manually and b) update existing or insert a new row if needed
Considering this is constrained device, which way is preferable? What if I omit the the extra requirement of sub-string match and always append uid to existing uid field?
"If it is possible with sqlite in one sql statement":
Yes, it is possible. The "UPSERT" statement has been nicely discussed in this question.
Applied to your extended case, you could do it like this in one statement:
insert or replace into info (uri, cap, uid)
values ( 'http://example.com',
coalesce((select cap from info where uri = 'http://example.com'),'new cap'),
(select case
when (select uid
from info
where uri = 'http://example.com') is null
then '|abc|'
when instr( (select uid
from info
where uri = 'http://example.com'),'|abc|') = 0
then (select uid
from info
where uri = 'http://example.com') || '|abc|'
else (select uid
from info
where uri = 'http://example.com')
end )
);
Checking the EXPLAIN QUERY PLAN gives us
selectid order from detail
---------- ---------- ---------- -------------------------
0 0 0 EXECUTE SCALAR SUBQUERY 0
0 0 0 SEARCH TABLE info USING INDEX sqlite_autoindex_INFO_1 (uri=?)
0 0 0 EXECUTE SCALAR SUBQUERY 1
1 0 0 EXECUTE SCALAR SUBQUERY 2
2 0 0 SEARCH TABLE info USING INDEX sqlite_autoindex_INFO_1 (uri=?)
1 0 0 EXECUTE SCALAR SUBQUERY 3
3 0 0 SEARCH TABLE info USING INDEX sqlite_autoindex_INFO_1 (uri=?)
1 0 0 EXECUTE SCALAR SUBQUERY 4
4 0 0 SEARCH TABLE info USING INDEX sqlite_autoindex_INFO_1 (uri=?)
1 0 0 EXECUTE SCALAR SUBQUERY 5
5 0 0 SEARCH TABLE info USING INDEX sqlite_autoindex_INFO_1 (uri=?)
As far as I know, sqlite will not cache the results of scalar sub-queries (I could not find any evidence of chaching when looking at the VM code produced by EXPLAIN for the above statement). Hence, since sqlite is an in-process db, doing things with two separate statements will most likely perform better than this.
You might want to benchmark the runtimes for this - results will of course depend on your host language and the interface you use (C, JDBC, ODBC, ...).
EDIT
A little performance benchmark using the JDBC driver and sqlite 3.7.2, running 100.000 modifications on a base data set of 5000 rows in table info, 50% updates, 50% inserts, confirms the above conclusion:
Using three prepared statements (first a select, then followed by an update or insert, depending on the selected data): 702ms
Using the above combined statement: 1802ms
The runtimes are quite stable across several runs.

Not sure about the type of SQL Server lock to use for synchronization

I have an ASP.NET web application that populates the SQL Server 2008 database table like this:
INSERT INTO tblName1 (col1, col2, col3)
VALUES(1, 2, 3)
I also have a separate service application that processes the contents of that table (on the background) by first renaming that table, and then by creating an empty table as such:
SET XACT_ABORT ON
BEGIN TRANSACTION
--Rename table
EXEC sp_rename 'tblName1', 'temp_tblName1'
--Create new table
CREATE TABLE tblName1(
id INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
col1 INT,
col2 INT,
col3 INT
)
COMMIT
SET XACT_ABORT OFF
--Begin working with the 'temp_tblName1' table
What I am not sure is which SQL lock do I need to use in this situation on the tblName1 table?
PS. To give you a frequency with which these two code samples run: first may run several times a second (although most times, less frequently), and the second one -- twice a day.
As some of the comments have suggested, consider doing this differently. You may benefit from using the snapshot isolation level. Using snapshot isolation requires ALLOW_SNAPSHOT_ISOLATION to be set to ON on the database. This setting is off by default, so you'll want to check whether you can turn it on.
Once you are able to use snapshot isolation, you would not need to change your INSERT statement, but your other process could change to something like:
SET XACT_ABORT ON
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
BEGIN TRANSACTION
-- Do whatever this process does, but don't rename the table.
-- If you want to get rid of the old records:
DELETE [tblName1] WHERE 1 = 1
-- Then
COMMIT TRANSACTION
In case you really do need to create a new non-temporary table for some reason, you may need to do so before entering the transaction, as there are some limits on what you are allowed to do during snapshot isolation.

Resources