We have an application that runs in MSAccess but utilizes SQL Server as the backend database. This generates a query to check which views it's got access to, and for normal users this takes up to 18 seconds. For all users that's member of the db_owner role, it takes 0.2 seconds. Is there any way I can tune this for normal users? Maybe something I can do in Access? I don't want to give them db_owner, and rewriting the application to not use Access is out of the question.
Here's the query:
select
object_name(id),
user_name(uid), type,
ObjectProperty(id, N'IsMSShipped'),
ObjectProperty(id, N'IsSchemaBound')
from sysobjects
where type = N'V'
and permissions(id) & 4096 <> 0
Using MS Access 2003, SQL Server 2008 R2
Short of figuring out the root cause of issue, maybe a work around might help? Just an idea: you could encapsulate your SQL statement in a proc owned by a db_owner and give it an EXECUTE AS clause. That way when a non db_owner called the proc the SQL in the proc would get executed under the impersonation of db_owner just for the duration and scope of the proc. Hopefully then your non db_owner users would benefit from the performance you're seeing when db_owner's run that SQL.
Bit late to the party but try this:
select
[name],
schema_name(schema_id),
[type],
Is_MS_Shipped,
Is_Schema_published
from
sys.all_views
where
not permissions(object_id) & 4096 = 0
Using the view specific object and inverting the comparison may give you slight improvement
Let me guess: You have an Access-ADP application that does this at startup. We had exactly the same. This query is used to get metadata that Access uses later. The root cause of the problem is the deprecated PERMISSIONS function:
http://msdn.microsoft.com/en-us/library/ms186915.aspx
Quote: "Continued use of the PERMISSIONS function may result in slower performance."
Since you cannot change either the query or the function, you are out of luck.
I suggest you consider moving to an ACCDB with linked tables, as ADP-support was cancelled in Access 2013 anyway.
Related
I have been given an Access Database that I have to try to decipher what it is doing.
As a start I see that there is a Pass Through query with a command like:
Exec RefreshGLTableLatestEntries
#sourceDB = 'DB_NAME' ,
#tablePrefix = 'TableName$' ,
#logFile = 'C:\logDB.txt'
When I run it I will get something like:
Result
Success... 108 rows inserted with a total amount of $0.000000
What I don't understand is where are the rows being copied from or copied to.
In the MSSQL database I don't see a table, query, standard procedure or function called 'TableName$'. There are quite a few tables & queries called 'TableName$SomethingElse'. Is there a way to see more details on where is the data coming from?
Similarly, how can I see where are the rows being inserted to? I can not find any file named 'logDB.txt' in my hard disk to see the log. I would suspect that it might not say much more that '...108 rows insterted...'
I'm using:
Access 2016 from Office 365, Version 1609
MS SQL Server Management Studio v17.1
Any ideas on how to get more information on how to get more information on what the Pass Through do?
A Pass-Through query in Access is equivalent to running its SQL code in SQL Server Management Studio.
(In the database that is designated by the connection string of the Pass-Through query.)
The SQL is sent as-is to MSSQL and run there.
RefreshGLTableLatestEntries is the stored procedure that is executed here. You need to locate and analyze it in SQL Server.
I have a console app that's geared to be automatically ran as a Scheduled Task. I use LINQ to SQL to pull some data out of the database, format it into a CSV and email it to a client. All of a sudden I am getting the error "SELECT permission denied for table", but the account I'm using to connect to the database (specified in my app.config file) has the "sysadmin" server role (bad programmer, I know; I'll get around to changing it to a better account later but I want to make sure it works first).
I can connect directly to the SQL database using that very same account and query the table in question without a problem, it only seems to be when using the LINQ code. Any idea what would be causing this?
Same server and database?
The error should actually say something like "does not exist or do not have permission". Now, if you're sysadmin then permission is irrelevant so table must not exist where you think it is
Ideas:
Wrong server
Client SQL alias pointing to wrong server
Wrong DB context
Wrong schema (eg SELECT * FROM bob.myTable should be SELECT * FROM fred.Mytable)
Try SELECT ##SERVERNAME, DB_NAME() (or Linq equivalent) to see where you are as a first step...
I have a weird problem here.
In short to the environment we have:
There is a (newly set up) Win2003 Server with a SQL Server 2005 Express database. I connect to it via a MS Access application.
Since I switched to the new server (restored a backup from the former server on it) all SPROCs (only in Access) have a ;1 after their name, hence cannot be found.
If I try to open a SPROC in Access (dbl click in overview), it asks for the parameter, then says cannot be found.
If I try to open, say, a report based on it, same result. If I change the name of the SPROC the report is based on to the name shown in the overview ( [sprocnam];1 ) it says "cannot be found" (of course, because the names did not change as one can see in Management Studio).
?!?
keep in mind that the Access-application worked fine with the database that I backed up on another server and restored to the newly set up server ...
Your help is greatly appreciated!
edit: I found a thread on SAP.com with someone experiencing the same problem, but without a solution: https://forums.sdn.sap.com/message.jspa?messageID=7947957
I can't tell why you have got this issue, but in In SQL Server you have the ability to create Numbered stored procedures. The procedures have the same name but may contain completely different code, look at this:
CREATE PROCEDURE [dbo].[spTest]
AS
BEGIN
SELECT ##MICROSOFTVERSION
END
GO
CREATE PROCEDURE [dbo].[spTest];2
AS
SELECT ##version
GO
EXEC spTest;1
EXEC spTest;2
I resolved the issue with an update of the clients office-installation to the latest service pack.
The one employee that notified me of the problem and me got new computers last week, and thus did not have the latest updates.
I have a SQL Server 2005 database that has been deleted, and I need to discover who deleted it. Is there a way of obtaining this user name?
Thanks, MagicAndi.
If there has been little or no activity since the deletion, then the out-of-the-box trace may be of help. Try running:
DECLARE #path varchar(256)
SELECT #path = path
FROM sys.traces
where id = 1
SELECT *
FROM fn_trace_gettable(#path, 1)
[In addition to the out-of-the-box trace, there is also the less well-known 'black box' trace, which is useful for diagnosing intermittent server crashes. This post, SQL Server’s Built-in Traces, shows you how to configure it.]
I would first ask everyone who has admin access to the Sql Server if they deleted it.
The best way to retrieve the information is to restore the latest backup.
Now to discuss how to avoid such problems in the future.
First make sure your backup process is running correctly and frequently. Make transaction log baclup evey 15 mintues or half an hour if it is a higly transactional database. Then the most you lose is a half an hour's worht of work. Practice restoring the database until you can easily do it under stress.
In SQL Server 2008 you can add DDL triggers (not sure if you can do this in 2005) which allow you to log who did changes to structure. It might be worth your time to look into this.
Do NOT allow more than two people admin access to your production database - a dba and a backup person for when the dba is out. These people should load all changes to the database structure and code and all of the changes should be scripted out, code reviewed and tested first on QA. No unscripted, "run by the seat of your pants" code should ever be run on prod.
Here is bit more precise TSQL
SELECT DatabaseID,NTUserName,HostName,LoginName,StartTime
FROM
sys.fn_trace_gettable(CONVERT(VARCHAR(150),
( SELECT TOP 1
f.[value]
FROM sys.fn_trace_getinfo(NULL) f
WHERE f.property = 2
)), DEFAULT) T
JOIN sys.trace_events TE ON T.EventClass = TE.trace_event_id
WHERE TE.trace_event_id =47 AND T.DatabaseName = 'delete'
-- 47 Represents event for deleting objects.
This can be used in the both events of knowing or not knowing the database/object name. Results look like this:
Following on from my last question:
I've written some code to upgrade a SQL Server database. Before I upgrade the database, I plan to limit access to the database with the following statement:
ALTER DATABASE Test SET SINGLE_USER WITH ROLLBACK IMMEDIATE
Before running this code, I'll give the user an opportunity to opt out. At the time of prompting the user, I thought it would be nice to show the list of active connections (continuously polled at a set interval); providing the user with a tool to identify applications/users they would like to boot off the server before proceeding.
In SQL 2000, you can use the sys.sysprocesses table to see all connections that apply to a database. This includes connections that have no active request (like when you open a Query Analyser window and select a database).
However, using:
sys.dm_exec_connections
sys.dm_exec_sessions; and
sys.dm_exec_requests
I couldn't figure out a way to achieve the same outcome. It appears that these views only tie connections to a database through a request. Is there a way to mimic the behaviour of sys.sysprocesses? I'd prefer not to use this table for SQL Server 2005/2008 databases.
Er... I recommended these for your other question.
Sorry, but, I've found out that you still have to use sysprocesses
It's logged as a bug in Microsoft Connect 144515 to be fixed, I found it here
Personally, I still use sysprocesses because I'm comfortable with it, however lazy and luddite that may be...