I encountered a problem yesterday. When I recreate a stored procedure which selects data from a view, the permissions have been revoked for view objects (like used tables in view) for all users except for the current user. For example;
The version of sybase ase is 12.5
Procedure;
drop proc testproc
go
create proc testproc
as
begin
....
select * from testView
....
end
go
grant exec on testproc to public
go
View;
create view testView as
select * from testTable
go
grant all on testView to public
go
And the error is
SELECT permission denied on object 'testTable', database 'Mytest',
owner 'dbo'.
I don't think you're creating the view as DBO.
If testTable is DBO, why would you have your view belonging to another user?
Related
I want to call the procedure created in main account from a reader account
I have couple of tables shared between them:
Employee
Procedure
Procedure table contains procedure names (to be called in main account) and id.
Calling the procedure as below but unable to do so
set var1 = (select procedure_name from procedure_calls);
call $var1;
Please let me know is it possible to call the way I am calling ?
I want to call the procedure created in main account from a reader
account
Currently, you can't do this from a reader account. A reader account can run select queries on the tables and secure views its parent account shares to it, and that's all it can do. It can't run other statement types including CALL.
You need to wrap the string with the stored procedure name in a literal identifier():
set sp = 'Load_Employee';
call identifier($sp)()
https://docs.snowflake.com/en/sql-reference/identifier-literal.html
Example - I have a stored procedure
copy_into_temp_table(table_name VARCHAR)
It can be called via the below statement
CALL copy_into_temp_table(EMP_TBL);
Hi and apologies in advance if the question has already been asked. I haven't been able to come across the answer.
I'm wondering if there is a table that holds a record of oracle usernames that have executed a particular procedure or function.
I'm trying to create a procedure that can be called as a subprogram by another procedure. The procedure which i'm looking to create will create a log entry every time the other procedure is executed. Example below;
User_Name = The Oracle user name of the person who executes the function.
Name = The name of the procedure or function.
LastCompileDT = The date/time the function or procedure was last compiled.
I'm a bit stuck on where to source the data from.
I've come across the all_source table but it only gives me the owner of the procedure and not the executing user.
Any feedback would be greatly appreciated.
Thanks
There might be a couple of ways to do that. Maybe someone else can suggest a method of extracting all this data from one data dictionary view. However, my method would be like this:
User_Name: use the keyword USER. It returns the Oracle user that executed the procedure:
SELECT USER FROM DUAL;
However, if you are interested in the OS user who executed that procedure, then you can use the following
SELECT sys_context( 'userenv', 'os_user' ) FROM DUAL;
More on this here. To my knowledge, this can be fetched on the fly only, and it is not logged anywhere by default. So you need to run it when you call the procedure.
Procedure Name: &
LastCompileDT : can be fetched from the view USER_OBJECTS
SELECT OBJECT_NAME, LAST_DDL_TIME
FROM USER_OBJECTS
WHERE OBJECT_TYPE = 'PROCEDURE'
AND OBJECT_NAME = '<YOUR PROCEDURE NAME>';
Rather than rolling your own audit, you could use the inbuilt auditing table provided.
See https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_4007.htm
--Create a test procedure as an example
CREATE PROCEDURE my_test_proc
AS
BEGIN
NULL;
END my_test_proc;
--Turning on auditing executions of the proc
AUDIT EXECUTE ON my_test_proc BY ACCESS WHENEVER SUCCESSFUL;
--Run the proc
EXEC my_test_proc;
--check audit history
SELECT *
FROM dba_common_audit_trail cat
WHERE cat.object_name = 'MY_TEST_PROC';
The dba_common_audit_trail table has columns DB_USER, and OBJECT_NAME for your User_Name/Name.
For the last compiled time see Hawk's answer, or if you want to see a history of last DDL times you can add this to the audit
--Turn on auditing of creating procs
AUDIT CREATE PROCEDURE BY ACCESS;
Migrating 1.5 million lines of D7,BDE,Paradox to XE2,ADO,MS-SQL.
We have a TDBLookupComboBox that works fine. We provide the user with an ellipsis button so they can add or delete records from the combo box's ListSource table while the combo box is visible.
If the user clicks on the ellipsis, we let them edit the table and then we Refresh the comboboxes datasource, like this:
EditTable.ShowModal; // user edits ListSource.Dataset table
Form1.DBComboBox1.ListSource.DataSet.Refresh
This worked fine in the Paradox world.
In the SQL/ADO world, if the user deletes a record from the ListSource, we get the message on the Refresh statement above:
Key value for this row was changed or deleted at the data store.
The local row is now deleted.
This occurs even if the record the user deleted was not the currently selected item in the combo box.
We don't understand why this is happening now but not in the Paradox version.
Our solution has been (after the user edits) to close and open the ListSource dataset as shown below, but this is clumsy (and we'll have to replicate in almost 100 places we do this kind of thing.)
Here's our current fix:
var
KeyBeforeUserEdit: Integer;
KeyBeforeUserEdit:= Form1.DBComboBox.KeyValue;
EditTable.ShowModal; // user edits ListSource.Dataset table
Form1.DBComboBox1.ListSource.DataSet.Close;
Form1.DBComboBox1.ListSource.DataSet.Open;
if Form1.DBComboBox1.ListSource.DataSet.Locate('UniqueKey', KeyBeforeUserEdit, []) then
From1.DBComboBox1.KeyValue := KeyBeforeUserEdit;
Any alternate suggestions or explanations why this is necessary?
I can't know for sure what is going on but you may be able to simplify your migration (albeit not good practice) in the following way.
ShowModal is a virtual function so you can override it in the class EditTable belongs to (TEditTable?) providing that you have that source. Within the unit add the Form1 unit to the uses clause in the implementation section (if it is not already there) and add your override as follows
function TEditTable.ShowModal : integer;
var
KeyBeforeUserEdit: Integer;
begin
KeyBeforeUserEdit:= Form1.DBComboBox.KeyValue;
Result := inherited ShowModal; // user edits ListSource.Dataset table
Form1.DBComboBox1.ListSource.DataSet.Close;
Form1.DBComboBox1.ListSource.DataSet.Open;
if Form1.DBComboBox1.ListSource.DataSet.Locate('UniqueKey', KeyBeforeUserEdit, []) then
From1.DBComboBox1.KeyValue := KeyBeforeUserEdit;
end;
It is a bit of a kludge but may be pragmatic and save a lot of work.
Wondering if someone can help me understand how a DB2 before insert trigger behaves. I have a Grails app that inserts rows to a DB2 database. The table in question has a before insert trigger that updates the date and user for the update:
CREATE TRIGGER WTESTP.SCSMA11I NO CASCADE BEFORE INSERT ON
WTESTP.SCSMA01T REFERENCING NEW AS NEWROW FOR EACH ROW MODE
DB2SQL BEGIN ATOMIC SET NEWROW.LST_UPDT_TMSP =
CURRENT_TIMESTAMP ; SET NEWROW.USER_ID = RTRIM ( USER ) ; END ;
In my Grails application I set all the values, including the user id:
flatAdjustmentInstance.setUserID("TS37813")
We use a generic application ID and password via JNDI to make the connection to the database. For auditing purposes I need to set the value of the user to whomever logged into the application. Is the only solution to remove the trigger entirely and just be really sure it is set?
The DB2 USER variable (also called "special register") contains the authorization ID of the current database connection. If an application wishes to pass another user ID to DB2, it can do so by calling the API function sqleseti() or the stored procedure WLM_SET_CLIENT_INFO() -- more info here. The trigger can then reference another special register, CURRENT CLIENT_USERID.
How can i associate a row of a list box with a row of a DB table?
I created a firemonky mobile application. On the form i drop a listbox. The listbox is filled with an item from a database.
zQuery1.Close;
ZQuery1.Open;
ListBox1.Items.Clear;
While not ZQuery1.Eof do
Begin
ListBox1.Items.Add(ZQuery1.Fields[1].AsString);
ZQuery1.Next;
end;
ZQuery1.Close;
Displayed is the name of a person.
Now when i doubleclick on the name of the person i want the open a second form with detailed information from that person (available in record). Can someone help me if this can be done?
I want to create an app on iPad so when someone taps on the detail button in the listbox there is more information of that person.
Instead of using listbox.items.add, you need to use listbox.items.addobject. For the purposes of the code below, I am assuming that the primary key of the table will be returned in zquery1.fields[0].
zQuery1.Close;
ZQuery1.Open;
ListBox1.Items.Clear;
While not ZQuery1.Eof do
Begin
ListBox1.Items.AddObject (ZQuery1.Fields[1].AsString,
tobject (zquery1.fields[0].asinteger)
ZQuery1.Next;
end;
ZQuery1.Close;
In order to access the stored id, you would write something like this
avariable:= longint (listbox1.Items.Objects[listbox1.itemindex]);