How can I make a remote table in MS Access "write only"? - ms-access

I have a little MS Access application (I know, I know), which accesses a table on a remote MS SQL Server.
I also have a form, which allows the users to enter data into the table. The problem is, that I want the users not to be able to read or modify existing data, but I only want them to enter data and store it (the data is a bit sensitive).
I tried to grant only INSERT privileges to the user connecting to the database, resulting in the error, that the table is not accessible at all.
After googling, I couldn't find anything which would solve this issue.
So my question: How can I ensure, that the users only enter data, but do not modify or read existing data in MS Access (2003)?

I would remove select permissions from the table (as you already have done) and do all the IO through a stored procedure. That way you can control exactly what is inserted into the system
Let me know if you need help running a stored procedure in ADO and I will post something up

I prefer a stored proc, but thought this was an alternate to give access to a view of the table with a check option
create table testview (somevalue varchar(25), entereddate datetime)
go
insert into testview values( 'First Value', getdate() )
go
create view testview_currentonly
as
SELECT
somevalue
, entereddate
FROM testview
WHERE entereddate >= getdate()
with check option
-- end view create
go
insert into testview_currentonly values( 'Second Value', getdate() )
select * from testview_currentonly
select * from testview
You can't select anything from this view because all entries (assuming the user could not manipulate the value going into the 'entereddate' field (probably should have a default?).

For the identity principal you use to access the remote SQL server table (this will be defined in the link), remove all permissions except db_datareader.
You can do this with MS Access permissions (but be warned: it's quite a difficult area...):
Microsoft Access Database Security - Security Permissions
Types of permissions (MDB)

Finally here's what I've done:
First, I created two tables:
CREATE TABLE mydata (...)
CREATE TABLE mydata2 (...)
Then I created an INSTEAD OF trigger:
CREATE TRIGGER mytrigger ON mydata
INSTEAD OF INSERT
AS
INSERT INTO mydata2 SELECT * FROM INSERTED
END
This moved every single entry from mydata to mydata2 on insert. The form in Access remained on mydata though, which made the entries invisible to the user.
Thanks to CodeSlave, who also suggested this solution

Related

Read Only linked table in Access to a SQL view - does not work

I have an ODBC connection created in MS Access 365. This is used to create a linked table in Access to a view in my SQL DB. I am using a SQL login to authenticate with SQL DB. The login has the datareader role set for that DB
If I make any changes to a record in the linked table in Access, those changes are also made in the SQL DB.
How can I avoid any changes in the Access linked table being propagated into the SQL DB?
You can add a trigger to the view like this:
CREATE TRIGGER dbo.MySampleView_Trigger_OnInsertOrUpdateOrDelete]
ON dbo.MySampleView
INSTEAD OF INSERT, UPDATE, DELETE
AS
BEGIN
RAISERROR ('You are not allow to update this view!', 16, 1)
END
You can also in a pinch add a union query, but it is somewhat ugly - you have to match up the column types. Eg:
ALTER VIEW dbo.MySampleView
as
SELECT col1, col2 FROM dbo.MySampleTable
UNION
SELECT NULL, NULL WHERE 1 =0
You can also create a new schema. Say dboR (for read only).
Add this new schema to the database. Then add the schema to the sql user/logon your using for this database. And then set the permissions to the schema to read only.
You have to re-create the view and choose the read-only schema for this view. On the access client side, I in most cases remove the schema default "dbo_" and just use the table (or view name) - you can thus continue to use the same view name you have been using in Access.

How to select temporary tables in Temporary Tables

Currently, I have some temp tables as this format "#A0089D2C", "#A0232241"
How could I select them to see what are its data?
I tried these queries as below:
Select * from #A0089D2C
Select * from tempdb.dbo.#A0089D2C
But I got the error:
Database name 'tempdb' ignored, referencing object in tempdb.
Database name 'tempdb' ignored, referencing object in tempdb.
Msg 208, Level 16, State 0, Line 1
Invalid object name '#A0089D2C'.
Please advise.
Thanks.
Technically, only that user who created the local temporary table can access it within the scope.
That means, local temporary table (# tables) can be accessed within the same scope by the same user while global temporary table(## tables) can be accessed among all the users until the last user session that references the table disconnects.
you can check table schema via below trick:
Right click on Tempdb database
Task > Export Data
Keep source database as TempDb
Select destination (Remember: you can not transfer data)
On Select source table and view form you will see "Edit mapping". Click on that to see table structure
but if you are really enthusiastic to see data in temporary table then check out this awesome post about viewing another session's Temporary table by Paul White
this should work, at least if the temp-table exists at the moment.
Select * from tempdb.dbo.#A0089D2C
See, temp tables are like the Schrodinger cat, they exists and they don't in the same time ;)

MYSQL statement works when entered in framework, can't get framework to work with function when saved mysql

History etc:
Project is time sheeet entry, currently works in excel now moving to DB
using excel 2010 as front end for rapid application development.
Framework is SAVETODB
I am not a DB expert, i have known how to write select stmt for years but first time designing complete DB
Goal: Saving database table changes entered in excel back to mysql
using mysql stored procedures (it works when the stored procedures code is saved in savetodb)
Not sure how much help I will get on here for SAVETODB (can't locate a product specific form), I have never used it before but if it works then it is brilliant for my needs.
So in SAVETODB you can enter your update/insert/delete queries or you can point it to your saved procedures in your db (mysql). When I enter my mysql statements into savetodb i can save to db from excel, but when saving as procedures in mysql and calling from savetodb i cannot save to db from excel.
The reason I say this isn't working is the savetdb "save" button is greyed out when loading second table
Starting out with getting a couple of fields in order to get the statements correct,
WORKS (ie savetodb allows saving changes) all code in savetodb - these are savetodb settings (green in linked image)
Doesn't work, ie using stored procedures these are savetodb settings (pink in linked image)
edit 0215 updated graphic below, savetdb can also accept a base table if referenced as insert/update/delete procedure. this needs the database name prefaced to table, but even with the database name prefaced to the procedure it still doesn't allow saving. maybe i am referencing the procedure wrong ?
data from framework file 'savetodb_deb.query_list'
[https://drive.google.com/file/d/0B20N5606_8JfTk9DZjVTVTFDaEE/view?usp=sharing]
The following three do work and update data/perform as expected when run from Navicat
MYSQL code for insert procedure - These three are what I am trying to get to work with the second set of savetodb settings
CREATE DEFINER = `root`#`localhost` PROCEDURE `NewProc`(IN `id` int,IN `thenumber` char(25),IN `thedate` datetime)
BEGIN
INSERT INTO time1
set Date = thedate, Reference = thenumber;
END;
MYSQL code for update procedure
CREATE DEFINER = `root`#`localhost` PROCEDURE `NewProc`(IN `idin` int,IN `thenumber` char(25),IN `thedate` datetime)
update `test`.`time1`
SET
`Reference` = 'poop', `Date` = '2015-01-15 00:00:00'
WHERE ID = idin;
MYSQL code for delete procedure
CREATE DEFINER = `root`#`localhost` PROCEDURE `NewProc`(IN `idin` int)
BEGIN
DELETE FROM time1
WHERE
ID = `idin`;
END;
Here is the link to the page at SAVETODB that talks about saving changes
http://
www.savetodb.com
/help4/configuring-saving-changes.htm
So this is actually quite simple within savetodb. Skip all the definer stuff and just enter in the query starting with "Select/insert/update" etc.
Savetodb is an excel add in, they actually create their own db/schema to save all the options so the queries we save as users are simply stored within a table.
to reference excel worksheet cells outside of the data table simply have excel name them (named range) then reference them in your query with : notation.

Log all events on all tables with MySQL

I need to log all events on all tables in table database_log (id, user, timestamp, tablename, old_value, new_value).
I thought I can create the same trigger on all tables (~25) with a little php script dynamically replace the name's table. But in this case I can retrieve the old and new value, because all tables haven't the same columns so I can't just concat all field for store in the "old_value" and "new_value" (even if I retrieve fields in schema because I can't use a concat() on it for select all value and store in variable).
For exemple a :
SELECT * into v_myvar FROM my_table where id=OLD.id;
CALL addLog(v_myvar)
Where addLog is procedure taking my old value and add a line with other informations, could save my life.
So, I'm looking for a sexy solution with one trigger and/or one procedure (by table) or a useful tool. Someone have a solution ?
Thanks
SET GLOBAL general_log_file = '/var/log/mysql/mysql.log';
The general query log is a general record of what mysqld is doing. The server writes information to this log when clients connect or disconnect, and it logs each SQL statement received from clients.
See the MySql Documentation

Using MySQL without any procedures or functions

Is it possible to use any sort of logic in MySQL without using any procedures? My web hosting does not let me create any procedures so I'm looking for a workaround.
The type of thing I want to do is only add an item to a table if it doesn't already exist. Or add a column to a table if it's not already there. There are some operations that can be done such as CREATE TABLE IF NOT EXISTS and so on, but some operations I require do not have such luxuries :(
I realised late on that my lovely procs won't work and so I tried writing IF/ELSE logic as top-level queries, but for MySQL, IF ELSE blocks only seem to work inside functions/procs and not at the global scope.
Any workarounds greatfully received - I've already asked the hosting to grant me privileges to create procedures but no reply as yet...
I suppose you don't have access to the INFORMATION_SCHEMA either. You can possibly find solutions but it would be better, in my oninion, to:
Change your hosting provider. Seriously. Pay more - if needed - for a MySQL instance that you can configure to your needs. You only have a crippled DBMS if you are not allowed to create procedures and functions.
Posible workarounds for the specific task: You want to add a column if it doesn't exist.
1) Just ALTER TABLE and add the column. If it already exists, you'll get an error. You can catch that error, in your application.
2) (If you have no access to the INFORMATION_SCHEMA) maintain a version of the schema, for your database.
The best solution that I can think of would be to use an additional language with SQL. For example, you can run a query for a specific record, and based on the response that you get, you can conditionally run an INSERT statement.
For inserting a table if it doesn't exist, try using the SHOW TABLES statement and testing whether or not a name exists in the result set.
MySQL supports INSERT IGNORE. and INSERT ... ON DUPLICATE KEY UPDATE.
The following will insert a new row, but only if there is no existing row with id=10. (This assumes that id is defined as a unique or primary key).
INSERT IGNORE INTO my_table (id, col1, col2) values (10, "abc", "def");
The following will insert a new row, but if there is an existing row with id=10 (again, assuming id is unique or primary), the existing row will be updated to hold the new values, instead of inserting a new row.
INSERT INTO my_table (id, col1, col2) values (10, "abc", "def")
ON DUPLICATE KEY UPDATE col1=VALUES(col1), col2=VALUES(col2)
Also, CREATE TABLE supports the IF NOT EXISTS modifier. So you can do something like:
CREATE TABLE IF NOT EXISTS my_table ...
There are many other similar options and modifiers available in MySQL. Check the docs for more.
Originally I created a big script to create or update the database schema, to make it easier to deploy database changes from my local machine to the server.
My script was doing a lot of "if table 'abc' exists and it doesn't have a FK constraint called 'blah'" then create an FK constraint called 'blah' on table 'abc'... and so on.
I now realise it's not actually necessary to check whether a table has a certain column or constraint etc, because I can just maintain a schema-versioning system, and query the DB schema-version when my app starts, or when I navigate to a certain page.
e.g. let's say I want to add a new column to a table. It works like this:
Add a new migration script to the app code, containing the SQL required to add the column to the existing table
Increment the app's schema-version by 1
On app startup, the app queries the DB for the DB's schema-version
If DB schema-version < app schema-version, execute the SQL migration scripts between the two schema-versions, and then update the DB schema-version to be the same as the app
e.g. if the DB's schema-version is 5 and the app version is 8, the app will apply migration scripts 5-6, 6-7 and 7-8 to the DB. These can just be run without having to check anything on the DB side.
The app is therefore solely responsible for updating the DB schema and there's no need for me to ever have to execute schema change scripts on the local or remote DB.
I think it's a better system than the one I was trying to implement for my question.