How can I allow users sql access to a table limited to certain rows? - mysql

I'm building an stock exchange simulation game. I have a table called 'Market_data' and in the game players simulate being in particular dates and are allowed to use SQL queries to retrieve the historical data and plan their course of action. My difficulty is that I need to limit the rows they can access based on the current date they are playing on so they cant see rows with a date greater than the current date.
Eg: An user is running the game and is currently in the year 2010, if he does a simple select like "SELECT * FROM market_data" I don't want him to see rows with Date > 'x-x-2010'
The only soution that I know of is to parse the user's SQL and add WHERE clauses to remove newer dates but it seems time consuming and prone to errors and I wasn't sure whether there were better alternatives. Any ideas on how to do this right will be thanked.

Solution is SQL Views, Views are used for several different reasons:
*1.*To hide data complexity. Instead of forcing your users to learn the T-SQL JOIN syntax you might wish to provide a view that runs a commonly requested SQL statement.
*2.*To protect the data. If you have a table containing sensitive data in certain columns, you might wish to hide those columns from certain groups of users. For instance, customer names, addresses and their social security numbers might all be stored in the same table; however, for lower level employees like shipping clerks, you can create a view that only displays customer name and address. You can grant permissions to a view without allowing users to query the underlying tables. There are a couple of ways you might want to secure your data:
a.Create a view to allow reading of only certain columns from a table. A common example of this would be the salary column in the employee table. You might not want all personnel to be able to read manager's or each other's salary. This is referred to as partitioning a table vertically and is accomplished by specifying only the appropriate columns in the CREATE VIEW statement.
b.Create a view to allow reading only certain rows from a table. For instance, you might have a view for department managers. This way, each manager can provide raises only to the employees of his or her department. This is referred to as horizontal partitioning and is accomplished by providing a WHERE clause in the SELECT statement that creates a view.
*3.*Enforcing some simple business rules. For example, if you wish to generate a list of customers that need to receive the fall catalog, you can create a view of customers that have previously bought your shirts during the fall.
*4.*Data exports with BCP. If you are using BCP to export your SQL Server data into text files, you can format the data through views since BCP's formatting ability is quite limited.
*5.*Customizing data. If you wish to display some computed values or column names formatted differently than the base table columns, you can do so by creating views.
reference taken from http://sqlserverpedia.com.

1)You can use mysql proxy http://dev.mysql.com/downloads/mysql-proxy/ with custom rules restricting access.
2)You can use stored procedures/functions
3)You can use views

The basic way would be :
-> Prevent that user (or group) from accessing the base table.
-> Define a view on top of that table that shows only the rows these users are supposed to see.
-> Give those users SELECT permission on the view.
-> And you can also use SQL Encryption,Decryption and Hashing concept.
Encryption & Decryption examples can be found here:
http://msdn.microsoft.com/en-us/library/ms179331.aspx
Hashing example can be found here:
http://msdn.microsoft.com/en-us/library/ms174415.aspx

Related

What do I gain from specifying relationships in my database?

I am building a project in MS Access 2010. I have previous experience in Oracle. I am reading about MS Access and keep seeing references to table relationships. It looks like a convenient way to assist the average person in data entry and validation and for query building, but I write queries exclusively in SQL mode and enforce data entry for users with forms that have their own validation rules.
Is it really necessary to enforce relationships? It doesn't seem like it really gains me anything at an advanced level, and might actually cause problems for me or someone else who eventually takes over maintenance from me later. I've never used them before and I'm not really seeing a benefit to starting now. Can anyone shed some light on that?
You say you have previous experience of Oracle. Did you never define Foreign Key constraints in Oracle? If you did, then that is what you are doing when you define relationships in Access. You can use it for enforcing referential integrity (not allowing you to delete a parent record if child records still exist) or, if you use the cascade delete option, for automatically deleting child records if you delete a parent record. It's a useful backup to cover coding errors where you might have forgotten about possible child records that would otherwise be orphaned if you did not have the relationship (FK) defined.
From a person just querying data, then the relationships are not that important. However from an application point of view, they are VERY helpful if not outright important.
For example, you might have a customer’s table, and then say an orders table. The business rule is that you can’t create an order unless you first have a customer. So if you freely write some SQL to add an order without a customer, your update/insert query will NOT work. And if you need to delete a customer, then all orders for that customer can/will automatic delete for you without having to write a complex delete SQL statement. You might for example want to delete all customers older than 5 or 10 years (so they are inactive). When you delete those customers, then you want all orders also deleted. (This is a VERY difficult query to write if you have to delete the child records for each customer. with enforced relations, then all child records will automatic delete for you (enforced cascade delete)).
And it also important from a reporting point of view. If you write a query to display all customers this month and their billing totals then you get one total result. However if you decide that you do NOT want to display/include customers, you might hit just the orders table and get a total amount that way. The problem is without RI, then you might (by accident or even just some user launching the orders form) have entered order information (with a total amount) but NO customer.
Now what happens is when you run the two different reports/quires, you find the total is DIFFERENT! In a complex application as to “why” the two reports are different can take days, or with lots of data even a week to figure out why two reports on monthly sales do NOT agree with each other. If you enforce the business rule that no orders can be entered into the system UNLESS they have a customer, then you eliminate such errors in reporting. You can “say” that you are perfect user of SQL, but with lots of code, lots of forms for data entry, how can you EVER be sure that orders are NEVER entered without a customer. The user during data entry may forget to enter the customer in that order form. And even if you write code in that order form to ENSURE that customer must be selected, maybe YOU during the writing of some SQL by accident insert an order record into the system without a customer. However your monthly customer total report query “assumes” that you have a customer record that you THEN join in the order totals data.
However some reports must just run on the orders data (a monthly summary total does not need to include customers). The problem now is somewhere in the system you have an order record with total data that does not have a customer. The result is different reports and quires on sales total now don’t agree. This is an outright nightmare.
So some bug or error in the application code might occur and result in what is supposed to be relational data now having “orphaned” records. Perhaps your business rules allow entering of orders without a customer assigned, but then your monthly sales report will have to show that fact, or any query that hits the orders table and does not include customers will have to “check” for the possibility in those queries that no customer record yet exits.
The above is only a SIMPLE scratching of the surface of the GAZILLION issues that crop up. So while you might be just creating simple quires on the data, the problem is that data correctly related in the system? The old saying about garbage in = garbage out rings true here.
At the end of the day when you’re SQL quires pulls data with MULTIPLE tables, then you HAVE to make assumptions about that data and its relational integrity (RI). So when you write that query to display customers and their order totals, you ASSUME and drop in the customers table, and then relational join in the orders table. However if orders exist without a customer record, then your query not going to produce the correct values. And worse a report that hits the orders table will now produce different results.
If you enforce RI then no matter what, you cannot enter an order by accident or force without FIRST having created a customer record. If you don’t enforce such rules, then your data will produce incorrect results.
And a typical complex application will have 40 or 70 related tables. And EVERY ONE of those tables is going to have assumptions made as to if parent (or child) record are “assumed” to have been created correctly based on your set of business assumptions.
You might have a tour booking system. Customers might phone up, put down a deposit but NOT yet be booked to a particular tour. If you allow this setup, then your query on customers this month and their booked tour will have to take this into account. However maybe the business rules are that any customer in the system that puts money down MUST ALSO be booked to a tour (and thus you query to grab that information will take this rule into account).
If every query you always made never was to include data from more than one table, then you likely don’t benefit much from enforcing relational data. However the instant you start bundling queries with multiple tables, then you MUST know the assumptions being made about that data before you can write a query. So do you allow customers with a deposit in the system without a tour booking or not? This rule will decide how you must write that query. If RI is enforced, then you can query on a customer “booking” that and you KNOW that it will be attached to a tour event. And same goes if any booking + deposit does not need a booking – but you HAVE to know the assumption made about that data.
So based on assumptions made about the data is the ONLY practical way to create a query to pull data based on those assumptions. And if you enforce RI, then you at least know the data MUST be related and setup based on those assumptions.
At the end of the day? Anyone creating a data base that models a business application and rules without enforcing RI is building a ship without rudder and without a compass.
And exporting data from each table is a NON issue. However if that data is a mess and has orphaned records, then you only wind up exporting a incorrect data model to another database and all of the issues and problems remain.
If you are building queries purely in SQL mode, defining the relationships probably doesn't make any difference for you. The only thing that might be useful is that if you built something, then didn't look at it again for a few months, you would be able to quickly re-acquaint yourself with the relationships conceptually.
For anyone using the access query builder, defining the relationships allows you to quickly add tables to the query while Access automatically builds the proper (GIGO) relationships for the query JOIN. Again, if you are writing in SQL, you probably already do this, so not much help for you in query building.
Bottom Line - it's more of a graphical tool to streamline the query process, at least until you try exporting the tables to a "real" RDBMS, as someone else already mentioned.
If its not a requirement for you use case then you don't necessarily have use this. A use case where this could be "required" is in an Order Based Scenario.
Lets say you have a Database that creates and tracks Orders. Each Order can have multiple Lines that are tied to the same Order. But for Normalization purposes, most people would separate these into two separate tables. OrderHead and OrderDetail. You would want to enforce Referential Integrity here to ensure that there is never a child record in OrderDetail that doesn't link back to a Parent Order.
I'm sure that you could prevent things like that without it, but it mainly just enforces it.
Relationships helps in preserving data integrity and I agree with your point that if user is entering from access form, probability of errors due to integrity is lesser. But in future if user is moving from MS Access to pure RDBMS, this relationship will definitely will be helpful.
Though objective of relationship is not for migration at later point-in-time, for your case that is one valid reason I could think-of.
Other than that, for MS Access with its own forms relationship may not add specific values.

Indefinite number of tables vs indefinite number of row with multiple columns

Which one would be better (performance wise and maintenance), a database which creates table dynamically or just adding rows dynamically?
Suppose I am building a project in which I let users to register. Say I have a table which store only basic personal infos, like name, dob, Date of joining, address, phone, etc. Say 10 columns.
Now is the tricky part.
Scene 1: Creating multiple tables
When a user complete registration, a message table is created. So each table is created for each users. The rows of each message table varies for each user.
In the same way there is a cart table for each user like the message table.
For this scene 1, 2 tables are created with every registration.
Scene 2: Adding Rows
The scenario is same here as well, but in this case I have 2 tables for message and cart. Rows are added only when there is an activity.
Note:
You must assume that the number of users is more than 2000 and expect 50+ users to be active all the time. Which means the message and cart tables are always busy for both the cases. Like there is always a query for update, add, delete, insert, select etc. simultaneously.
Also which scene will consume more disk space.
While writing this, it make me wonder what technique would Facebook and others use. If they use the Scene 2 style (all users (billions) use the same big long message table)... Just wondering
Databases has some basic rules defined for Database Design called
"Database Normalization", These basic rules allow us eliminating
redundant data.
1st Normal Form
Store One piece of information in only One Column, A column should store only One piece of information.
2ns Normal Form
A Table should have only the columns that are related to each other. All the related columns should be in One table.
Now if you look at your advised design, A Separate Table for each USER
will split SAME information/Columns about all the user in 1000's of
tables. Which violates the 2nd Normal Form.
You need to Create One Table and put all the related Columns in that
one table for all the users. and you can make use of normal t-sql to
query your data but if you have a table for each user my guess is your
every query that you execute from your application will be built
dynamically and for every query you will be using dynamic sql. which
is one of the Sql Devils and you want to avoid using it whenever
possible.
My suggestion would be read more about Database Design. Once you have
some basic understanding of database design. Draw it on a piece of
paper and see if it provides you everything that your business
requires / expects from this application , Spend sometime on it now it
will save you a lot of pain later.

How to enable users only to view certain rows in a table

I currently have two tables. One is accounts and one is tbl_units_info. My boss wants me to make it so that accounts are restricted from reading certain rows in a table. Frankly, I think my boss has no idea what he is talking about, but I'm hoping someone here can prove me wrong.
For example, accountname krikara can only view the entries of the tbl_units_info table where the TBID column is 0909.
Is this even possible? To make krikara only able to view the rows in that table where column TBID = 0909?
It can not be implemented plainly on DBMS level since SELECT privilege has table level. You can not restrict rows reading. And this is good, I think - because data could be changed, so in general there is no solid condition for rows restriction (and, therefore, there could not be valid implementation for that on DBMS level).
You can, however, use VIEW - but it is a middlepoint, not common solution (I still not think it will help with tracking rows changes, but may be I'm wrong due to your application logic)
You can try to implement it in your application, but it still has problem I've described above: in table, data is changing. You'll probably have troubles with tracking all changes. I think you can separate your rows on two (several) tables and then build your permissions model. But - if some basically similar entities must have different permissions - probably you should reconsider application security model?
You could solve it by giving accounts just the reading rights to a view instead of the whole table.
CREATE VIEW `tbl_units_info_krikara` AS
SELECT * FROM `tbl_units_ino` WHERE `TBID`='0909';
And then assign the respective rights to your user.
MySQL CREATE VIEW documentation

Regex for SQL string to allow SELECT queries on variable named tables only?

The table names are variable, but what is certain is that SELECT only is allowed and certain tables are excluded (ie Users, Log). I'm making a reporting form where a user can just enter sql queries to make template reports.
SELECT 'field1' As 'foo', 'field2' as 'bar'.. 'fieldn'
FROM 'table1',..'tablen'
JOIN ... ON ...
WHERE CONDITION
Although I'm thinking I can have the table names in a html select list of existing tables.
Also make a user reporter_appname#localhost with SELECT access only to all tables except Users and Log? In that case I won't need to bother with a regex check of the query?
(This would be in PHP)
(Ideally I just wanted a single textarea where the admin can just type their query, my report function would then take the output and present it nicely etc.)
I suggest you re-think your design.
Identifying valid select statements (and excluding all other statements) is basically impossible without completely parsing SQL. A regex is not going to be up to the task.
Even if you allow only select statements, users could perform denial-of-service attacks on your database. It is very easy to create select statements that run forever (we've all done it). A malicious user could crash your site in a hurry. And even well-intentioned users might do this by accident.
It would be much better to give the users more limited options for creating reports. Let them select certain tables and columns from a list, and create the appropriate query for them.
There is probably free MySQL reporting software out there that could serve as a good starting point, though I don't have any experience with this myself.
I think that you should rethink the design of your application.
The Users and Log tables should be on one database and the tables with the data for the reports should be on another database.
If you have them all in one database already just create another database, link them and then create synonyms from one database to another only for the tables that the user can access via his queries.
The user will run his queries on the database you have just created and he will be limited to those tables that have synonyms on it.
I do not know if this would be the best option because your description of the case is relatively vague but based on the information I have this could be a solution.

Access How to save text in a specific table?

Within my database i have 3 different tables for different members. When saving the members details i use a form to save the members all to the same table but i would like to save them to a specific table depending on their details. for example if a member has registered with their school email i would like them to be saved within the student table, if they have used a freemail email address to be saved in the freemail table etc
Would this be run as a query or sorting the one table using if statements?
You probably should not have three tables, just a field that defines the member type. You may wish to read Fundamentals of Relational Database Design.
If you really insist on having three tables, even though it is likely to cause ever more tangled scenarios, you will either have to use VBA to gather the data from an unbound form and then fill it into the appropriate table, or ask the user which table they wish to update before you start and set up the form for that table.
It depends on your development environment. You can either change the switch to an If clause at business level or you can implement it as a database procedure. It's up to you.
http://msdn.microsoft.com/en-us/library/aa933214(v=sql.80).aspx explains how to use If clause in database