How to tell when a sql table was last accessed - sql-server-2008

This question is basically an extension of this question:
How can I tell if a database table is being accessed anymore? Want something like a "SELECT trigger"
In the query the author provided as a solution in his post, I assume a null value would mean that a table hasn't been accessed since the last time SQL Server was restarted.
My question is: Is there a way to tell when a table was last accessed, if the last access was before the last time SQL restarted? Also, how can I tell when the last time SQL was restarted?

For sql server start time in SQL Server 2008,
select sqlserver_start_time from sys.dm_os_sys_info
For last user access since server restart,
select DB_NAME(us.[database_id]) as [db], OBJECT_NAME(us.[object_id], us.[database_id]) as [object],
MAX(us.[last_user_lookup]) as [last_user_lookup], MAX(us.[last_user_scan]) as [last_user_scan], MAX(us.[last_user_seek]) as [last_user_seek]
from sys.dm_db_index_usage_stats as us
where us.[database_id] = DB_ID() AND us.[object_id] = OBJECT_ID('tblname')
group by us.[database_id], us.[object_id];
I log this table daily so I have it after restarts. It can also act as an index audit after they have been dropped.

Related

How to set a date/time in front-end access that is compatible with back-end SQL?

We use Access 2016 as a front end and SQL Server 2008 as back end.
A user creates a new record in a form. In order to generate an autonumbered ID for this new record, I use DoCmd.RunCommand acCmdSaveRecord. When I use this command, the form moves off of that record. I need to then find the ID of the record just created. I cannot search for the largest autonumber ID because we use merge replication and different users have different ID ranges.
I tried making a DateCreated column and defaulting that column to the current date and time by using GetDate() in SQL Server, but that that makes Access give lock errors and other errors because it cannot properly read SQL Server's datetime format.
Is there a .saverecord option that doesn't move off the current record in a form? Or is there a date/time field that won't produce an error when using SQL Server backend and Access frontend?
In a nutshell, I need the autonumbered ID of the last record created in a form.
Use a Pass through query to run this SQL statement after you insert your record:
SELECT SCOPE_IDENTITY() AS ID
It will return the last created identity used in the current scope.
To get the auto number field to populate in an Access form bound to a sql server table you simply need to force the form to save the record. The act of saving the record does not and should not and will not move the form off of the record.
The code to get the auto number is thus:
If me.Dirty = True then Me.Dirty = false
Debug.print "Auto number from SQL server = " & me!id
You as a general rule cannot use SELECT SCOPE_IDENTITY() since the connection used in the form will be different then the connection you use to execute the SQL pass-through query. So the responses here are wild goose chase and incorrect and the wrong way to approach this problem.
Run another command in the same session to get the id:
SELECT ##IDENTITY
For more details check the: MSDN documentation.
Anyway, if you have an API to access the database, and it doesn't expose this, it should be expended to return the scope identity, since this is the only reliable way to know what ID was generated.

Eror when updating the mysql table on linked server, from mssql server

When I try to update my customer table that is on linked server, from my procedure on mssql server, I get this error:
OLE DB provider "MSDASQL" for linked server "PRESTA" returned message "Row cannot be located for updating. Some values may have been changed since it was last read.".
Msg 7343, Level 16, State 4, Line 1
The OLE DB provider "MSDASQL" for linked server "PRESTA" could not UPDATE table "[PRESTA].. [prs_customer]". The rowset was using optimistic concurrency and the value of a column has been changed after the containing row was last fetched or resynchronized.
I am 100% sure that the value I am trying to put in the birthday column of my Customer table is not the same as the value that is already in it:
UPDATE PRESTA...prs_customer
SET birthday = #birthday
WHERE id_customer = #id_customer
This error is showing only because the value already in birthday column is: "0000-00-00", and not null. When I change directly in database to real NULL, my procedure works, and it doesn't give any errors.
Also, both values are of type DATE, have the same format, so that is not a problem.
I am baffled by this, so if anyone please elaborate?
Just read the error message. The link server is using optimistic concurrency. Thus, a record is read via a cursor in the OLE DB layer. When you try to perform the update, the data has changed. Optimistic means use locking just before you do an update.
Are you sure this is the exact SQL statement?
Are there any other processes that might change the id during your update?
Check out the ADO book from MS Press.
http://web.archive.org/web/20021222065228/http://www.microsoft.com/mspress/books/sampchap/3445.asp
It shows the same error you are experiencing.
Unless it is a bug in the OLE DB provider or MySQL, it looks to me as a locking issue.
Can you increase the locking level to pessimistic? If you do, you will have to handle blocking in your code.
I would also run a trace in MySQL to see what statements are hitting the DB Engine.
Sincerely
John

How to get last access date for a SQL Server database?

I have a development server that is getting crowded.
I would like to see what date the databases have been accessed to determine what ones can be deleted. Is there a way to do this?
The only thing I found when searching was for postgredb:
How to get last access/modification date of a PostgreSQL database?
If you have a table that always gets values inserted you can add a trigger to the update/insert. Inside this trigger you can set the current timestamp in a dedicated database, including the name of the database from which the insert took place.
This way the only requirement of your database is that it supports triggers.

Querying MySQL and MSSQL databases at the same time

I'm getting data from an MSSQL DB ("A") and inserting into a MySQL DB ("B") using the date created in the MSSQL DB. I'm doing it with simple logics, but there's got to be a faster and more efficient way of doing this. Below is the sequence of logics involved:
Create one connection for MSSQL DB and one connection for MySQL DB.
Grab all of data from A that meet the date range criterion provided.
Check to see which of the data obtained are not present in B.
Insert these new data into B.
As you can imagine, step 2 is basically a loop, which can easily max out the time limit on the server, and I feel like there must be a way of doing this must faster and during when the first query is made. Can anyone point me to right direction to achieve this? Can you make "one" connection to both of the DBs and do something like below?
SELECT * FROM A.some_table_in_A.some_column WHERE
"it doesn't exist in" B.some_table_in_B.some_column
A linked server might suit this
A linked server allows for access to distributed, heterogeneous
queries against OLE DB data sources. After a linked server is created,
distributed queries can be run against this server, and queries can
join tables from more than one data source. If the linked server is
defined as an instance of SQL Server, remote stored procedures can be
executed.
Check out this HOWTO as well
If I understand your question right, you're just trying to move things in the MSSQL DB into the MySQL DB. I'm also assuming there is some sort of filter criteria you're using to do the migration. If this is correct, you might try using a stored procedure in MSSQL that can do the querying of the MySQL database with a distributed query. You can then use that stored procedure to do the loops or checks on the database side and the front end server will only need to make one connection.
If the MySQL database has a primary key defined, you can at least skip step 3 ("Check to see which of the data obtained are not present in B"). Use INSERT IGNORE INTO... and it will attempt to insert all the records, silently skipping over ones where a record with the primary key already exists.

SQL Server 2008 Linked Server and CONTEXT_INFO

I'm trying to use the SQL Server 2008 Change Tracking feature. Once the feature is enabled, you can make use of the CHANGETABLE(... function to query the change tracking history that is kept internally by SQL Server, e.g.:
SELECT
CT.ID, CT.SYS_CHANGE_OPERATION,
CT.SYS_CHANGE_COLUMNS, CT.SYS_CHANGE_CONTEXT
FROM
CHANGETABLE(CHANGES dbo.CONTACT,20) AS CT
where the SYS_CHANGE_CONTEXT column records the CONTEXT_INFO() session value. This column is useful for auditing who changed what etc.
Some of the statements that change data are executed using four-part notation by a remote SQL Server that has the home server as a linked server e.g.:
INSERT INTO [home server].[db name].[dbo].[CONTACT](id) values(#id)
My problem is that the CONTEXT_INFO() as set on the remote server in the session executing the query does not get picked up in my home server change tracking, i.e. it doesn't look like the CONTEXT_INFO spans a distributed query. This means that the following will not result in the CONTEXT_INFO being logged on the home server change tracking.
-- I'm running on a remote server
WITH CHANGE_TRACKING_CONTEXT (0x1256698477)
INSERT INTO [home server].[db name].[dbo].[CONTACT](id) values(#id)
Does anyone know whether this is a limitation or if there is a way to persist/communicate CONTEXT_INFO across the distributed query?
Thanks
I was thinking about using Context_Info to audit changes (web app). but after doing some tests understood its not good idea. Because of connection pooling context_info was not working the way i desired.
Ended up with using GUID identifier associated with each logical session + table, where is stored session GUID and information related to session + each table stores that identifier in separate column. Not as easy to code as it would be with context_info()..
And as far as i understood from documentation, change tracking is not designed for audit purposes (think that is what you trying to do).