How to mask field values to some specific users? - sql-server-2014

In SQL Server 2014, we always run our queries from our server side code as a specific SQL "system" user. However, there is an "app user" in any given query context.
So, when a query like this is run:
select field1 from table1;
Our business wants field1 value to be masked based on the "app user". Info on which field should be masked for which app user is/can be setup in the database.
What is the best way to support this in SQL 2014? Seems like I might have to start by building a view, even so, how do I go about masking some column values there based on the current app user?

Related

Save MySql 'Show' result in db

So I'm kind of stumped.
I have a MySql project that involves a database table that is being manipulated and altered by scripts on a regular basis. This isn't so unusual, but I need to automate a script to run (after hours, when changes aren't happening) that would save the result of the following:
SHOW CREATE TABLE [table-name];
This command generates the ready-to-run script that would create the (empty) table in it's current state.
In SqlWorkbench and Navicat it displays the result of this SHOW command in a field in a result set, as if it was the result of a SELECT statement.
Ideally, I want to take into a variable in a procedure, and change the table name; adding a '-mm-dd-yyyy' to end of it, so I could show the day-to-day changes in the table schema on an active server.
However, I can't seem to be able to do that. Unlike a Select result set, I can't use it like that. I can't get it in a variable, or save it to a temporary, or physical table or anything. I even tried to return this as a value in a function, from which I got the error that a function cannot return a result set - which explains why it's displayed like one in the db clients.
I suspect that this is a security thing in MySql? If so, I can totally understand why and see the dangers exposed to a hacker, but this isn't a public-facing box at all, and I have full root/admin access to it. Hopefully somebody has already tackled this problem before.
This is on MySql 8, btw.
[Edit] After my first initial comments, I need to add; I'm not concerned about the data with this question whatsoever, but rather just these schema changes.
What I'd really -like- to do is this:
SELECT `Create Table` FROM ( SHOW CREATE TABLE carts )
But this seems to be mixing apples and oranges, as SHOW and SELECT aren't created equal, although they both seem to return the same sort of object
You cannot do it in the MySQL stored procedure language.
https://dev.mysql.com/doc/refman/8.0/en/show.html says:
Many MySQL APIs (such as PHP) enable you to treat the result returned from a SHOW statement as you would a result set from a SELECT; see Chapter 29, Connectors and APIs, or your API documentation for more information. In addition, you can work in SQL with results from queries on tables in the INFORMATION_SCHEMA database, which you cannot easily do with results from SHOW statements. See Chapter 26, INFORMATION_SCHEMA Tables.
What is absent from this paragraph is any mention of treating the results of SHOW commands like the results of SELECT queries in other contexts. There is no support for setting a variable to the result of a SHOW command, or using INTO, or running SHOW in a subquery.
So you can capture the result returned by a SHOW command in a client programming language (Java, Python, PHP, etc.), and I suggest you do this.
In theory, all the information used by SHOW CREATE TABLE is accessible in the INFORMATION_SCHEMA tables (mostly TABLES and COLUMNS), but formatting a complete CREATE TABLE statement is a non-trivial exercise, and I wouldn't attempt it. For one thing, there are new features in every release of MySQL, e.g. new data types and table options, etc. So even if you could come up with the right query to produce this output, in a couple of years it would be out of date and it would be a thankless code maintenance chore to update it.
The closest solution I can think of, in pure MySQL, is to regularly clone the table structure (no data), like so:
CREATE TABLE backup_20220618 LIKE my_table;
As far as I know, to get your hands on the full explicit CREATE TABLE statement, as a string, would require the use of an external tool like mysqldump which was designed specifically for that purpose.

RedShift Query via SSRS with user parameters: Say WHAT?

I'm trying to create a query that grabs records that fall within a specified time frame, hence BETWEEN. However, I need to do this from an interactive report which user can specify the endDate and startDate parameters.
I've read that RedShift may not necessarily support variables or parameters and that I may need to use temp tables, but my requirements are that users can pass in values. I'm confused on how using temp tables with pre-defined values allows for in-determinant values to be passed to the base query...
Here's my initial attempt (dont laugh)
prepare prep_select_plan(date)
AS select TOP 10 * from table WHERE date BETWEEN $1 AND $2;
EXECUTE prep_select_plan(#startDate);
EXECUTE prep_select_plan(#endDate);
DEALLOCATE prep_select_plan;
Is there another platform that would allow me to create a web based, interactive report with the ability to have end users enter parameter values?
Update*
I've attached the dataset properties window to elicit feedback on how to pass value to the RedShift query.
When connecting to a database like RedShift or MySQL using ODBC, you have to use a more generic syntax for parameters. Rather than using the # symbol and the parameter name, you just use a ? in the query. For example, one line would look like this:
EXECUTE prep_select_plan(?);
You can map which report parameters go to the query parameters in the parameters tab of the dataset properties. The parameters are simply mapped in the order they appear, you can't reference the same name in multiple places in the query. It's not as user friendly, but SSRS is primarily designed to work with SQL Server.

Access Continuous Form with Linked Table - How to Avoid Hitting Database Server for Every Row in Form?

I'm migrating the data from an Access database to SQL Server via the SQL Server Migration Assistant (SSMA). The Access application will continue to be used with the local tables converted to linked tables.
One continuous form hangs for 15 - 30 seconds when it's loading. It displays approximately 2000 records. When I looked in SQL Server Profiler to see what it was doing, it was making a separate call to the backend database for each record in the form. So the delay when the form opens is caused by the 2000-odd separate calls to the database.
This is amazingly inefficient. Is there any way to get Access to make a single call to the backend database and retrieve all the records at once?
I don't know if this is relevant but the Record Source for the form is a view in the SQL Server backend database, which is linked to via an Access linked table (so, hopefully, Access just sees it as a table, not a view). I needed an Instead Of trigger on the view in SQL Server, and a unique index on the linked table in Access, to allow the records to be updated via the form.
If the act of opening that continuous form really does generate ~2000 separate SQL queries (one for every row in the view) then that is unusual behaviour for Access interacting with a SQL Server linked "table". Under normal circumstances what takes place is:
Access submits a single query to return all of the Primary Key values for all rows in the table/view. This query may be filtered and/or sorted by other columns based on the Filter and Order By properties of the form. This gives Access a list of the key values for every row that might be displayed in the form, in the order in which they will appear.
Access then creates a SQL prepared statement using sp_prepexec to retrieve entire rows from the table/view ten (10) rows at a time. The first call looks something like this...
declare #p1 int
set #p1=4
exec sp_prepexec #p1 output,N'#P1 int,#P2 int,#P3 int,#P4 int,#P5 int,#P6 int,#P7 int,#P8 int,#P9 int,#P10 int',N'SELECT "ID","AgentName" FROM "dbo"."myTbl" WHERE "ID" = #P1 OR "ID" = #P2 OR "ID" = #P3 OR "ID" = #P4 OR "ID" = #P5 OR "ID" = #P6 OR "ID" = #P7 OR "ID" = #P8 OR "ID" = #P9 OR "ID" = #P10',358,359,360,361,362,363,364,365,366,367
select #p1
...and each subsequent call uses sp_execute, something like this
exec sp_execute 4,368,369,370,371,372,373,374,375,376,377
Access repeats those calls until it has retrieved enough rows to fill the current page of continuous forms. It then displays those forms immediately.
Once the forms have been displayed, Access will "pre-fetch" a couple of more batches of rows (10 rows each) in anticipation of the user hitting PgDn or starting to scroll down.
If the user clicks the "Last Record" button in the record navigator, Access again uses sp_prepexec and sp_execute to request enough 10-row batches to fill the last page of the form, and possibly pre-fetch another couple of batches in case the user decides to hit PgUp or start scrolling up.
So in your case if Access really is causing SQL Server to run individual queries for every single row in the view then there may be something particular about your SQL View that is causing it. You could test that by creating an Access linked table to a single SQL Table or a simple one-table SQL View, then use SQL Server Profiler to check if opening that linked table causes the same behaviour.
Turned out the problem was two aggregate fields. One field's Control Source was =Count(ID) and the other field's Control Source was =Sum(Total_Qty).
Clearing the control sources of those two fields allowed the form to open quickly. SQL Server Profiler shows it calling sp_execute, as Gord Thompson described, to retrieve seven batches of 10 rows at a time. Much quicker than making 2000 calls to retrieve one row at a time.
I've come across the same problem again but this time with a different cause. I'm including it here for completeness, to help anyone in a similar situation:
This time the underlying query was hanging and SQL Server Profiler showed the same behaviour as before, with Access making separate calls to the SQL Server database to bring back one record at a time, for every record in the query.
The cause turned out to be the ORDER BY clause in the query. I guess Access had to pull back all records in the linked table from SQL Server before being able to order them. Makes sense when I think of it. Although I don't know why Access doesn't just pull all records through at once, instead of getting the records one at a time.
I would try setting the Recordset Type to Snapshot (on the Data tab of the Form's property sheet and/or the property sheet of the query you are using for the form source)

can make stored procedure or function in Access 2003?

In Access 2003, can we create stored procedure or function?
For Access 2003, the answer is no.
Access 2010 does have table triggers and store procedures. These are true engine level routines that run as a result of row updates. So forms or VBA recordset code or sql updates that cause a row modify will cause the store procedure and table level code to run. In fact, even external connections via ODBC from vb.net, or even VB6 will cause these store procedures to run.
However prior to Access 2010 you do not have store procedures if you use the default database engine. However, you can choose a different data engine then JET for your Access applications and when you do this then yes you can have store procedures, but you have to use the tools that come with whatever data base engine you have chosen to use with Access. So, keep in mind that just like when you build a web site, you then can go out and choose what database engine you use. The same goes for ms-access and you are free to go out and choose a database engine that has store procedures to be used with Access.
As noted, the exception to this is that Access 2010 does have table level triggers and store procedures now.
Not "Stored Procedures" as such. You can create saved queries and call those from Access in the same way as stored procs form Sql Server. The limitations that the saved queries have are that you cannot use control of flow code (such as If Else or Case When) and you can only save one command at a time.
The simplest way to create saved queries is to open up Access, go the Query tab and create a new query in Design View. Close the Show Tables dialogue box and switch to SQL View. Using the example above, type in the first part of the SQL clause:
INSERT INTO Addresses ( Organisationname, AddressLine1, AddressLine2,
AddressLine3, City, StateCounty, CountryID, PostCodeZip, SwitchboardNo,
FaxNo, Email, Website, RecordStatus, LastUpdated, LastUpdateBy )
Values
Now open the brackets and create the parameter place holders. These are always in square brackets ( [ ] ), which tells Access to expect a value as a parameter. You can put anything you like within the square brackets. [p1], [p2], [p3] etc are my choice, so the final query will look like this:
INSERT INTO Addresses ( Organisationname, AddressLine1, AddressLine2,
AddressLine3, City, StateCounty,CountryID, PostCodeZip, SwitchboardNo, FaxNo,
Email, Website, RecordStatus, LastUpdated, LastUpdateBy ) Values ([p1],[p2],[p3],
[p4],[p5],[p6],[p7],[p8],[p9],[p10],[p11],[p12], [p13],[p14],[p15]);
If you Run the query, Access will prompt you for input for each field. Enter data against each field to test that the query is working. As for debugging, you've just done it. Save the query as something meaningful. This one is saved as qUpdateAddresses. As you save it, you may notice that Access automatically detects that this is an Append Query. Once you have verified that it works, close the database.
to run it from ASP.NET, look at this article, paying attention to the bit towards the end that's headed "Saved Queries":
http://www.mikesdotnetting.com/Article.aspx?ArticleID=26

Automatically print out orders

I am wanting to create a VB.Net app that checks a database and then prints out the latest orders, the database is mysql and i need it to periodatically check and only print new orders i.e. not print ones it has already printed out.
Any advice would be greatly appriciated.
Kyle
My suggestion is to add a printed flag to your database, i.e. add a printed field in the database which stores 0 by default denoting the entry has not been printed and a 1 that denotes the entry has been printed.
I would then create an application which checks the database table for all entries where flag = 0.
These entries are the ones that need printed.
Print each entry an set its flag to 1 in the database. Setting the flag to 1 ensures that the next time you poll the database the entries will be ignored.
I'd recommend breaking the problem down into pieces:
"checks a database" - you'll need to create a connection to a relational database. You'll have to set up either an ADO.NET or ODBC connection to MySQL.
You don't say if the database is running on the same machine as the app. If it's not, you'll have to be able to connect to it on the network.
Make sure that you GRANT the appropriate permissions in MySQL. Don't just use the admin credentials to log in. Set up a separate ID for your app.
"then prints out" - your app will have to find a way to acquire information about a printer. You don't say if it's connected directly to the server on which the job will run or if it's a networked printer. Be sure your app can see the networked printer if it's the latter.
"the latest orders, the database is mysql" - try writing a separate query to test getting only the latest orders.
Does your schema include a way to mark which orders have been printed and when? Your app should INSERT a record noting the timestamp when each order is printed. You can JOIN on this table to figure out what the latest, unprinted orders are.
"and i need it to periodically" - your app needs to be a cron job that's run on a schedule that you specify. Every weekday, hourly? Once a night? You decide when you set up the cron job.
You could try using LINQ and dbLINQ for connecting with MySQL. If you are using .NET Framework 3.5 you may as well take advantage of something like LINQ to speed up development time.
If using WPF for the client application you could use a FlowDocument to layout the order details and then handle printing of the orders. Once they are printed you can update the database or store details locally to mark that order as printed. It depends on your database schema.