SSRS 2008 subscriptions have incorrect data - sql-server

I have written, and rewritten, a hospital census query for which I would like to create a daily Windows File Share subscription. The query seems fine; it runs properly in SSMS, BIDS, and on the SSRS Report Server itself. However, when I create any kind of subscription, sometimes the report will have old and incorrect data on it. There is no real pattern to when the report generates incorrectly, as far as I can tell, but the data that gets sent incorrectly is consistently the same, and is from back in January. I had initially written the query on a test server with the same data, just a little bit older, and had changed the dates that it would run for. I also had to re-deploy the report a few times after making changes. I had initially deployed it from the test system directly to the live server, so I tried completely redoing it in the live system, in addition to making some changes improve performance, but I am still getting the same incorrect data.
Any ideas would be greatly appreciated at this point, because I am at a loss and I am really just getting started with SQL.
Thank you for any assistance.
Edits: adding the queries that are returning the inconsistent data; removing my comments that have poorly-formatted code.
Also, to be a bit more specific about the issue: The subscription sometimes sends the census data for the day before as expected, and sometimes it sends the census data from January 15, and this only happens in the subscription.
Query 1:
SELECT
V.Name AS PatientName
,V.AccountNumber AS AccountNumber
,V.FinancialClassName AS FinancialClass
,V.ServiceDateTime
,P.EmergencyID AS Provider
,X.ErDateTime AS Discharge
,X.ErDispositionID AS Disposition
FROM dbo.AdmVisits AS V
INNER JOIN dbo.AdmProviders AS P
ON P.VisitID=V.VisitID
INNER JOIN dbo.AdmDischarge AS X
ON V.VisitID=X.VisitID
WHERE CAST(V.ServiceDateTime AS DATE)=CAST(DATEADD(day,-1,GETDATE()) AS DATE)
OR CAST(X.ErDateTime AS DATE)=CAST(DATEADD(day,-1,GETDATE()) AS DATE)
ORDER BY V.Name
Query 2:
SELECT
V.Name
,V.AccountNumber
,V.FinancialClassName
,V.InpatientServiceID
,V.RoomID
,D.AdmitDateTime
,P.AdmitID
,P.AttendID
,X.DischargeDateTime
,X.DispositionName
FROM dbo.AdmVisits AS V
INNER JOIN dbo.AdmittingData AS D
ON V.VisitID=D.VisitID
INNER JOIN dbo.AdmProviders AS P
ON P.VisitID=D.VisitID
LEFT OUTER JOIN dbo.AdmDischarge AS X
ON V.VisitID=X.VisitID
WHERE V.InpatientOrOutpatient='I'
AND NOT V.InpatientServiceID='INP LTC'
AND (CAST(D.AdmitDateTime AS DATE)<CAST(GETDATE()AS DATE))
AND (V.Status='ADM IN' OR CAST(X.DischargeDateTime AS DATE)=CAST(DATEADD(DAY,-1,GETDATE()) AS DATE))
ORDER BY V.Name
Query 3:
SELECT
V.Name
,V.AccountNumber
,V.FinancialClassName
,V.InpatientServiceID
,V.RoomID
,D.AdmitDateTime
,P.AdmitID
,P.AttendID
,X.DischargeDateTime
,X.DispositionName
,CASE
WHEN V.LoaStatus IN('F','L') THEN CAST(V.LoaEffectiveDateTime AS varchar)
Else 'No'
END AS 'LeaveOfAbsence'
FROM dbo.AdmVisits AS V
INNER JOIN dbo.AdmittingData AS D
ON V.VisitID=D.VisitID
INNER JOIN dbo.AdmProviders AS P
ON P.VisitID=D.VisitID
LEFT OUTER JOIN dbo.AdmDischarge AS X
ON V.VisitID=X.VisitID
WHERE V.InpatientServiceID='INP LTC'
AND (CAST(D.AdmitDateTime AS DATE)<CAST(GETDATE()AS DATE))
AND (V.Status='ADM IN' OR CAST(X.DischargeDateTime AS DATE)=CAST(DATEADD(DAY,-1,GETDATE()) AS DATE))
ORDER BY V.Name

So it turns out that the issue was the data source's connection string to the server. I was using 'localhost' instead of the server's actual name, and since the test and live servers are basically clones of one another, I think it wasn't consistently connecting to the right server. Not sure how exactly that works, but the report is working now.

Related

SSRS Report Manager: Linked report behaving strangely but SQL queries work fine

I have created a report (call it Primary) and a drillthrough (call it Secondary) in Report Builder. Each of these has a SQL statement.
When executed in SQL Server Management Studio, SQL statements work as expected.
However, when the Primary.rdl and Secondary.rdl are uploaded to Report Manager (the web interface in Internet Explorer), they do not generate the correct data when run.
Because of this, I think the problem is not the SQL statements. I think it's something to do with the Report Manager.
Primary SQL statement:
This statement grabs a bunch of user data from multiple tables and checks if their passwords are acceptable. It populates a list of users whose passwords failed the check.
This is pseudocode so pardon inconsistencies in var names
with details as (
select u.userid
, u.password
, u.firstname
, u.lastname
, u.userdescription
, u.status
, u.lastlog
, dbo.IsPassswordAcceptable(u.userid, u.password) as passStatus
from masterListOfUsers as u
)
select d.*, p.datavalue
from details as d
left join passwordDetailList as p
on p.keyvalue = d.passStatus
and p.datatype = 'ERRORMESSAGE'
where d.passStatus <> 1
and d.passStatus <> -5
and d.status = (#USERSTATUS) -- only user ids in use
;
Secondary SQL statement:
This statement is a drillthrough. The person running the report can click on a userID in the above list. A drillthrough is performed where the contact information for that userID is populated.
This is pseudocode so pardon inconsistencies in var names
SELECT
m.userid
, c.address
, c.city
, c.state
, c.zip
, c.cphone
FROM userMasterList AS m
left join userDetailList AS d
ON d.userid = m.userid
left join anotherList as e on d.fullkey = e.fullkey
left join yetAnotherList AS c
WHERE m.userid = #USERID;
Expected result:
When the user runs the Primary, a list of users with bad passwords is populated. Each user's userID can be clicked on, which triggers the Secondary to populate the location/contact info associated with that userID.
Actual result:
On userID click, the Secondary fails to populate any location/contact info associated with the userID. This occurs only sometimes. Other times, it works fine.
I made a list of these "empty" userIDs and ran the Secondary's SQL statement in Management Studio, and it populates all the expected location/contact info.
Solutions I've tried:
I'm absolutely stumped. I've triple-checked the SQL statements and tested them in Management Studio. I've re-uploaded both .rdl files to Report Manager. I've reassigned the Secondary to the Primary via the "Create Linked Report" option in Report Manager AND ALSO in Report Builder's Action > Go To Report option.
What else can I do?
This is not really an answer as such, but a list of things I would work thru in the same situation.
Run SQL Profiler to trace your report session and make sure the query being executed is what you expect. Depending on how parameters are passed to the SQL statements, SSRS will not always do things quite the way you expected.
Check if you can repeat the issue by just running the drill thru report on it's own (not via the primary report)
Determine if the issue is consistent with specific userids? i.e. does user A always fail and User B always work? If the issue is consistent, the issue is most likely to be data related. Check for special characters in the fields that appear to be blank such as chr(13)/chr(10), they may just be forcing the 'real' content onto a new line inside the textbox.
Add some debug info to your report to help identify the issue such as:
a. Edit the dataset query to add some more info from dataset itself SELECT .... , c.addrees, len(c.address) as AddresLen from .... You can add this to a copy of your report
b. Add another textbox that does the same thing but directly in SSRS (e.g. expression would be something like =LEN(Fields!address.Value)). You then have two numbers to compare against what you can see. If the LEN textbox says 20 but the address field appears blank, then special characters could be the issue.
After hours of tinkering, the problem ended up being that the userID was being trimmed of all leading and trailing whitespace by some of the query tools but not by the SQL statements themselves. So when the final report is run in Report Manager, the data is queried with superfluous whitespace, resulting in no data being found.
This issue is resolved when the data points are trimmed.
The fixed Secondary SQL statement:
This is pseudocode so pardon inconsistencies in var names
SELECT
rtrim(m.userid) as userid
, rtrim(c.address) as address
, rtrim(c.city) as city
, rtrim(c.state) as state
, rtrim(c.zip) as zip
, rtrim(c.phone) as phone
FROM userMasterList AS m
left join userDetailList AS d
ON d.userid = m.userid
left join anotherList as e on d.fullkey = e.fullkey
left join yetAnotherList AS c
WHERE ltrim(rtrim(m.userid)) = ltrim(rtrim(#USERID));

How to pull a ms access report data to a query?

I am trying to pull data from a MS Access report (repInvoices and form frmInvoice) and keep it in MS Access query(qryQuote). I know how it can be done from form but not from a report. I did research in stack exchange and google but I didn't find anything that is helpful. Can any of you help me out? Following is the query that I had been trying to work on. I kept form on following example:
SELECT MAX([oi].[Quote])
FROM ORDER_Shipment AS os
INNER JOIN ORDER_Items AS oi
ON os.Id = oi.Id
AND oi.MaterialId = [Reports]![repInvoices]![MaterialId]
WHERE os.InvoiceNumber= CAST('& Me.InvoiceID' AS VARCHAR)
Two last lines in above query is the place where I need to get data from the report.Also, I know both of above are not correct right now.
[Reports]![repInvoices]![MaterialId] It gives me an error JOIN expression not supported.
Also, I have to use report InvoiceID here CAST('& Me.InvoiceID' AS VARCHAR)

ADODB.Recordset returns with incorrect data?

I have an ADO.Recordset object that is able to successfully connect to the database and pull data. However, the data that is in the database vs what is being retrieved by the object is incorrect.
For example, if I take the exact query that is in the command parameter in the Recordset and execute it in Sql Server Management Studio, the RANK in SSMS is 170 but the data returned in code from the object says it is 140.
Has anyone run across a situation like this before? I can't figure out why this is happening.
This involves a search box where the user is trying to search for a product and the script is trying to find the product that the user most likely wants to find.
SELECT tbl.RANK as rk, a.*, CA.* FROM FREETEXTTABLE
([ab_fts],([cpn],[cd],[mas],[ac],[ttr],[nemo],[man]),'tester',1000) tbl
INNER JOIN [qws] a on tbl.[key] = a.wid
INNER JOIN catad CA ON (CA.cgid = a.cgid)
ORDER BY rk DESC

Last Run Date on a Stored Procedure in SQL Server

We starting to get a lot of stored procedures in our application. Many of them are for custom reports many of which are no longer used. Does anyone know of a query we could run on the system views in SQL Server 2005 that would tell us the last date a stored procedure was executed?
The below code should do the trick (>= 2008)
SELECT o.name,
ps.last_execution_time
FROM sys.dm_exec_procedure_stats ps
INNER JOIN
sys.objects o
ON ps.object_id = o.object_id
WHERE DB_NAME(ps.database_id) = ''
ORDER BY
ps.last_execution_time DESC
Edit 1 : Please take note of Jeff Modens advice below. If you find a procedure here, you can be sure that it is accurate. If you do not then you just don't know - you cannot conclude it is not running.
In a nutshell, no.
However, there are "nice" things you can do.
Run a profiler trace with, say, the stored proc name
Add a line each proc (create a tabel of course)
"INSERT dbo.SPCall (What, When) VALUES (OBJECT_NAME(##PROCID), GETDATE()"
Extend 2 with duration too
There are "fun" things you can do:
Remove it, see who calls
Remove rights, see who calls
Add RAISERROR ('Warning: pwn3d: call admin', 16, 1), see who calls
Add WAITFOR DELAY '00:01:00', see who calls
You get the idea. The tried-and-tested "see who calls" method of IT support.
If the reports are Reporting Services, then you can mine the RS database for the report runs if you can match code to report DataSet.
You couldn't rely on DMVs anyway because they are reset om SQL Server restart.
Query cache/locks are transient and don't persist for any length of time.
Oh, be careful now! All that glitters is NOT gold! All of the “stats” dm views and functions have a problem for this type of thing. They only work against what is in cache and the lifetime of what is in cache can be measured in minutes. If you were to use such a thing to determine which SPs are candidates for being dropped, you could be in for a world of hurt when you delete SPs that were used just minutes ago.
The following excerpts are from Books Online for the given dm views…
sys.dm_exec_procedure_stats
Returns aggregate performance statistics for cached stored procedures. The view contains one row per stored procedure, and the lifetime of the row is as long as the stored procedure remains cached. When a stored procedure is removed from the cache, the corresponding row is eliminated from this view.
sys.dm_exec_query_stats
The view contains one row per query statement within the cached plan, and the lifetime of the rows are tied to the plan itself. When a plan is removed from the cache, the corresponding rows are eliminated from this view.
sys.dm_exec_procedure_stats contains the information about the execution functions, constraints and Procedures etc. But the life time of the row has a limit, The moment the execution plan is removed from the cache the entry will disappear.
Use [yourDatabaseName]
GO
SELECT
SCHEMA_NAME(sysobject.schema_id),
OBJECT_NAME(stats.object_id),
stats.last_execution_time
FROM
sys.dm_exec_procedure_stats stats
INNER JOIN sys.objects sysobject ON sysobject.object_id = stats.object_id
WHERE
sysobject.type = 'P'
ORDER BY
stats.last_execution_time DESC
This will give you the list of the procedures recently executed.
If you want to check if a perticular stored procedure executed recently
SELECT
SCHEMA_NAME(sysobject.schema_id),
OBJECT_NAME(stats.object_id),
stats.last_execution_time
FROM
sys.dm_exec_procedure_stats stats
INNER JOIN sys.objects sysobject ON sysobject.object_id = stats.object_id
WHERE
sysobject.type = 'P'
and (sysobject.object_id = object_id('schemaname.procedurename')
OR sysobject.name = 'procedurename')
ORDER BY
stats.last_execution_time DESC
If you enable Query Store on SQL Server 2016 or newer you can use the following query to get last SP execution. The history depends on the Query Store Configuration.
SELECT
ObjectName = '[' + s.name + '].[' + o.Name + ']'
, LastModificationDate = MAX(o.modify_date)
, LastExecutionTime = MAX(q.last_execution_time)
FROM sys.query_store_query q
INNER JOIN sys.objects o
ON q.object_id = o.object_id
INNER JOIN sys.schemas s
ON o.schema_id = s.schema_id
WHERE o.type IN ('P')
GROUP BY o.name , + s.name
This works fine on 2005 (if the plan is in the cache)
USE YourDb;
SELECT qt.[text] AS [SP Name],
qs.last_execution_time,
qs.execution_count AS [Execution Count]
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE qt.dbid = DB_ID()
AND objectid = OBJECT_ID('YourProc')
I use this:
use YourDB;
SELECT
object_name(object_id),
last_execution_time,
last_elapsed_time,
execution_count
FROM
sys.dm_exec_procedure_stats ps
where
lower(object_name(object_id)) like 'Appl-Name%'
order by 1

Stored procedures reverse engineering

We're having problem with a huge number of legacy stored procedures at work. Do you guys recommend any tool the can help better understand those procedures? Some kind of reverse engineering that indentifies inter-procedure dependencies and/or procedure vs. tables dependencies. Can be a free or commercial tool.
Thanks!
The cheaper solution than 'dependency tracker' is the data dictionary table sys.sql_dependencies which from which this data can be queried from the data dictionary. Oracle has a data dictionary view with similar functionality called DBA_DEPENDENCIES (plus equivalent USER_ and ALL_ views) . Using the other data dictionary tables (sys.tables/DBA_TABLES) etc. you can generate object dependency reports.
If you're feeling particularly keen you can use a recursive query (Oracle CONNECT BY or SQL Server Common Table Expressions) to build a complete object dependency graph.
Here's an example of a recursive CTE on sys.sql_dependencies. It will return an entry for every dependency with its depth. Items can occur more than once, possibly at different depths, for every dependency relationship. I don't have a working Oracle instance to hand to build a CONNECT BY query on DBA_DEPENDENCIES so anyone with edit privileges and the time and expertise is welcome to annotate or edit this answer.
Note also with sys.sql_dependencies that you can get column references from referenced_minor_id. This could be used (for example) to determine which columns were actually used in the ETL sprocs from a staging area with copies of the DB tables from the source with more columns than are actually used.
with dep_cte as (
select o2.object_id as parent_id
,o2.name as parent_name
,o1.object_id as child_id
,o1.name as child_name
,d.referenced_minor_id
,1 as hierarchy_level
from sys.sql_dependencies d
join sys.objects o1
on o1.object_id = d.referenced_major_id
join sys.objects o2
on o2.object_id = d.object_id
where d.referenced_minor_id in (0,1)
and not exists
(select 1
from sys.sql_dependencies d2
where d2.referenced_major_id = d.object_id)
union all
select o2.object_id as parent_id
,o2.name as parent_name
,o1.object_id as child_id
,o1.name as child_name
,d.referenced_minor_id
,d2.hierarchy_level + 1 as hierarchy_level
from sys.sql_dependencies d
join sys.objects o1
on o1.object_id = d.referenced_major_id
join sys.objects o2
on o2.object_id = d.object_id
join dep_cte d2
on d.object_id = d2.child_id
where d.referenced_minor_id in (0,1)
)
select *
from dep_cte
order by hierarchy_level
I've got this to open-up to the community now. Could someone with convenient access to a running Oracle instance post a CONNECT BY recursive query here? Note that this is SQL-server specific and the question owner has since made it clear that he's using Oracle. I don't have a running Oracle instance to hand to develop and test anything.
Redgate has a rather expensive product called SQL Dependency Tracker that seems to fulfill the requirements.
I think the Red Gate Dependency Tracker mentioned by rpetrich is a decent solution, it works well and Red Gate has 30 day trial (ideally long enough for you do do your forensics).
I would also consider isolating the system and running the SQL Profiler which will show you all the SQL action on the tables. This is often a good starting point for building a sequence diagram or however you choose to document these codes. Good luck!
Redgate SQL Doc. the generated documentation included cross-referenced dependency information. For example, for each table, it lists views, stored procedures, triggers etc that reference that table.
What database are the stored procedures in? Oracle, SQL Server, something else?
Edit based on comment: Given you're using Oracle then, have a look at TOAD. I use a feature in it called the Code Roadmap, which allows you to graphically display PL/SQL interdependancies within the database. It can run in Code Only mode, showing runtime call stack dependancies, or Code Plus Data mode, where it also shows you database objects (tables, views, triggers) that are touched by your code.
(Note - I am a TOAD user, and gain no benefit from referring it)
This isn't real deep or thorough, but I think that if you're using MS SQL Server or Oracle (Perhaps Nigel can help with a PL-SQL sample)...Nigel is on to something . This only goes 3 dependencies deep, but could be modified to go however deep you need. It's not the prettiest thing...but it's functional...
select
so.name + case when so.xtype='P' then ' (Stored Proc)' when so.xtype='U' then ' (Table)' when so.xtype='V' then ' (View)' else ' (Unknown)' end as EntityName,
so2.name + case when so2.xtype='P' then ' (Stored Proc)' when so2.xtype='U' then ' (Table)' when so2.xtype='V' then ' (View)' else ' (Unknown)' end as FirstDependancy,
so3.name + case when so3.xtype='P' then ' (Stored Proc)' when so3.xtype='U' then ' (Table)' when so3.xtype='V' then ' (View)' else ' (Unknown)' end as SecondDependancy,
so4.name + case when so4.xtype='P' then ' (Stored Proc)' when so4.xtype='U' then ' (Table)' when so4.xtype='V' then ' (View)' else ' (Unknown)' end as ThirdDependancy
from
sysdepends sd
inner join sysobjects as so on sd.id=so.id
left join sysobjects as so2 on sd.depid=so2.id
left join sysdepends as sd2 on so2.id=sd2.id and so2.xtype not in ('S','PK','D')
left join sysobjects as so3 on sd2.depid=so3.id and so3.xtype not in ('S','PK','D')
left join sysdepends as sd3 on so3.id=sd3.id and so3.xtype not in ('S','PK','D')
left join sysobjects as so4 on sd3.depid=so4.id and so4.xtype not in ('S','PK','D')
where so.xtype = 'P' and left(so.name,2)<>'dt'
group by so.name, so2.name, so3.name, so4.name, so.xtype, so2.xtype, so3.xtype, so4.xtype
How to find the dependency chain of a database object (MS SQL Server 2000(?)+)
by Jacob Sebastian
Every time he needs to deploy a new report or modify an existing
report, he needs to know what are the database objects that depend on
the given report stored procedure. Some times the reports are very
complex and each stored procedure might have dozens of dependent
objects and each dependent object may be depending on other dozens of
objects.
He needed a way to recursively find all the depending objects of a
given stored procedure. I wrote a recursive query using CTE to achieve
this.
The single best tool for reverse engineering is by APEX. Its amazing. It can even trace into .NET assemblies and tell you where the procs are used. Its by far the deepest product of its kind. RedGate has great other tools but not in this case.

Resources