Extend row-level security to a bridging table - sql-server

I am working on row level security in my database. I have two tables. Row based security is implemented on data_table and only returns rows that the user can see.
data_table:
data_id name role
-----------------------------
1 test USER
2 another ADMIN
3 yep USER
type_table:
type_id name
-----------------
1 this
2 is
3 a
4 type
EXECUTE AS USER = 'USER';
SELECT * FROM data_table;
returns rows 1 and 3 only. If you execute as ADMIN, all of the rows are returned. This is working properly in my database.
However, my issue is my bridging table.
data_type_table:
data_type_id data_id type_id
1 1 2
2 1 3
3 2 1
4 2 2
5 3 1
6 3 4
As of right now
EXECUTE AS USER = 'USER';
SELECT COUNT(data_type_id) FROM data_type_table;
returns 6 because it's looking at all 6 rows in the table. I'm trying to set it up in such a way that user USER will only see rows in data_type_table which are referencing rows where data_table.role = 'USER' (this means that the select count query would return 4). What would be the simplest way to implement something like this?
My data_table will more than likely contain hundreds of thousands of rows. Efficiency could become a problem here.

Related

How do I delete rows in one table where the ID matches another table row where a field is a certain value?

I admit the title question is convoluted; here is the situation.
I have two tables:
USERS Table
id
name
status
1
Monica
A
2
Ross
A
3
Phoebe
T
4
Chandler
A
5
Rachel
T
6
Joey
A
PERMISSIONS Table
user_id
permission_id
1
32
1
51
4
12
6
2
3
5
5
22
2
18
What I want is a way to delete all rows from the PERMISSIONS table where that user's STATUS is "T" but how would I do that?
I had tried this:
DELETE FROM permissions
WHERE user_id IN (
SELECT id FROM users
WHERE status = 'T'
);
However, SQL Server gives this error: Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
try apply join permissions and user and where status = 'T'
Example:
DELETE p
FROM permissions p
INNER JOIN users u
ON p.user_id=u.id
WHERE u.status = 'T'

Auto Generate Unique ID separate from Primary Key

I have a Relational database (that I'm new to creating) that has many tables relating to baseball statistical tracking and analysis. The table I'm working on currently is the tbl_PitchLog table, that tracks pitches in an at-bat.
What I'd like to do is eliminate the need for an at-bat table and just use At-Bat Unique ID for a group of pitches. I have a Pitch_ID field, but I'd like SS to generate a new AtBat_ID that I can then reference to get all the pitches of a particular at-bat.
For Example
Pitch_ID | Pitch_Number | Result
1 1 Foul
2 2 Foul
3 3 Strike
4 1 Ball
5 2 Flyout
6 1 Groundout
To be:
Pitch_ID | AtBat_ID | Pitch_Number | Result
1 1 1 Foul
2 1 2 Foul
3 1 3 Strike
4 2 1 Ball
5 2 2 Flyout
6 3 1 Groundout
You don't specify what version of SS you're using, but SQL Server 2012 introduced sequences; you can create an at bat sequence, get the next value when the at bat changes, and use that value for your inserts.
CREATE SEQUENCE at_bat_seq
AS INTEGER
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE <what you want the max to be>
NO CYCLE;
DECLARE #at_bat int;
SET #at_bat = NEXT VALUE FOR at_bat_seq;
Most of the qualifiers are self-explanatory; the [NO] CYCLE specifies whether the value will start over at the min when it hits the max. As defined above, you'll get an error when you get to the max. If you just want it to start over when it gets to the max, then specify CYCLE instead of NO CYCLE.
Create the tbl_PitchLog table with a Pitch_ID as its primary key, while it's at the same time a foreign key taken from the main table.
What you're looking for is a one to one relationship.

How to (or Can I) select a random value from the Postgresql database excluding some particular records?

Is it possible to randomly select a record from the database excluding some records with particular status?
For eg,
For example, I have a table for storing employee details.
id employeename employeestatus
1 ab 1
2 cd 1
3 ef 2
4 gh 1
5 ij 1
What I want from the query is to fetch a single random record whose status is not 2. Is it possible to do so? The database I'm using is PostgreSQL 8.4.15.
TRY This
SELECT *
FROM employee
WHERE employeestatus != 2
ORDER BY RANDOM()
LIMIT 1
Try this other question on the same topic
Best way to select random rows PostgreSQL
It's tricker than you think (to do efficiently)

EF or SQL Server - Computed / Continous Column

I'm not sure how to do this and where it should be implemented.
I have a table with columns: ID, TypeID, AIndex. Both the ID and TypeID are supplied when creating a new record. The AIndex is a continuous column based on both IDs.
To illustrate here an example:
ID TypeID Aindex
---------------------
1 1 1
1 1 2
1 2 1
1 3 1
2 1 1
2 1 2
The big question is:
They are lot of people writing to this table at a time?
When you compute Aindex column from previous database data, some thing like max( Aindex ) + 1 the risk is to induce locks.
If only few inserts are made in table you can write increment code in your favorite layer, EF or DB. But if your table has high write ratio you should search for a alternate technique like counters table or something else. You can keep this counters table with EF if you want.

Search Problem in SQL Server

I need to search in a table for items which have all of my desired values in a column i.e.
I have table :
ID : 1 2 3 3 2 2 2 1 1 3
VALUE : 5 6 5 3 6 7 2 1 9 0
I want to give a StoredProc a list of values for example ("6,7,2") and it returns me all IDs that have all the given values in this case it would only returns 2
If I wanted to search for those which at least have one of the values I know I could use "IN" but to have all the values i found nothing.
Thank you in advance
Afshin Arefi
In SQL Server 2008 you can use table value parameters.
These allow you to pass in a table of values to a stored procedure and treat it as any other table (use in sub-queries, joins etc).
In terms of the query - if you do use a table value parameter, you can query it for size (how many rows), use IN in conjunction with a GROUP BY on the ID field and a HAVING that counts the number of rows.

Resources