SQL Server trigger reports 'inserted' table is missing - sql-server

I am running a script against a SQL Server 2016 database that creates various tables, views and triggers. This same script has been working against dozens of other servers but it is getting an error against this one particular server.
All of the triggers seem to be created but when I check for invalid objects it reports all of them as invalid. The really strange part is, it says the problem is the "inserted" table (or "deleted" table, depending on the trigger) is missing.
I am checking for invalid objects using this query:
SELECT
QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.'
+ QuoteName(OBJECT_NAME(referencing_id)) AS ProblemObject,
o.type_desc,
ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name) AS MissingReferencedObject
FROM
sys.sql_expression_dependencies sed
LEFT JOIN
sys.objects o ON sed.referencing_id = o.object_id
WHERE
(is_ambiguous = 0)
AND (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name)) IS NULL)
ORDER BY
ProblemObject,
MissingReferencedObject
which I got from here
Find broken objects in SQL Server
The triggers are "instead of" triggers against the views that then modify the underlying tables. There is really nothing special about any of them.
Is there something wrong with my query and the objects aren't really invalid or is there something with the database? I am running the script as the database owner so I don't think it is a permissions issue.
Thanks

Run this query against the problem SQL Server, and against one where no problems are shown:
SELECT *
FROM
sys.sql_expression_dependencies sed
LEFT JOIN
sys.objects o ON sed.referencing_id = o.object_id
WHERE type = 'TR'
ORDER BY
type_desc,
referenced_entity_name
If the inserted / deleted tables show up in one list but not the other, then there is some difference causing this. I'd check identifier quoting rules to start.

Related

Convert SQL.Bak to BacPac

I'm using SQL server 2012, I have a Database file (.bak) trying to export it to a (.BacPac) file so I can import it to Azure. The problem is in the converting progress (Validating scheme model),
I have the following error :
"Error SQL71501: View: [dbo].[AC_Section] has an unresolved reference to object [dbo].[sueres].".
"Error SQL71562: Procedure: [dbo].[milp] has an unresolved reference to object [tempdb].[dbo].[sysob].[xtyp]."
and the errors are going with many other tables and objects.
How do I solve this or if there is another way to convert the database to .bacpac.
Try to resolve invalid objects before migrating the database to SQL Azure. Invalid objects are objects (stored procedures, views, etc.) that are making reference to objects no longer exist, including objects on tempdb.
SELECT
QuoteName(OBJECT_SCHEMA_NAME(referencing_id)) + '.'
+ QuoteName(OBJECT_NAME(referencing_id)) AS ProblemObject,
o.type_desc,
ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name) AS MissingReferencedObject
FROM
sys.sql_expression_dependencies sed
LEFT JOIN sys.objects o
ON sed.referencing_id=o.object_id
WHERE
(is_ambiguous = 0)
AND (OBJECT_ID(ISNULL(QuoteName(referenced_server_name) + '.', '')
+ ISNULL(QuoteName(referenced_database_name) + '.', '')
+ ISNULL(QuoteName(referenced_schema_name) + '.', '')
+ QuoteName(referenced_entity_name)) IS NULL)
ORDER BY
ProblemObject,
MissingReferencedObject
I would like to recommend you using Data Migration Assistant before migrating the database to SQL Azure. This tool does not detect invalid objects at this time.
Microsoft Data Migration Assistant v3.1
Hope this helps.
Regards,
Alberto Morillo
So I came to a conclusion that some data, functions, tables, objects and etc... in my (.bak) file are not supported by Azure, or you can say they're outdated. The ways to deploy the (.bak) file to Azure is by avoiding, deleting or re-write these data before deploying the file to Azure, which is going to change the data flow.

Display file path of documents in Crystal Report

I have a crystal report that lists invoices and I would like to be able to show the file path of the invoices in another column of the report. The following query allows me to search for the documents based on their unique ID number. It then displays the file location of the one document I search for, however I would like to have this apply to all of the documents listed in the report. Can someone please help me out with this?
`DECLARE #entryID INT = 35793
SELECT dbo.toc.name AS DocumentName, dbo.doc.pagenum + 1 AS PageNum, dbo.vol.fixpath + '\' +
SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),1,2) + '\' +
SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),3,2) + '\' +
SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),5,2) + '\' +
CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2) + '.TIF' AS FullPathAndFilename
FROM dbo.doc
LEFT JOIN dbo.toc ON dbo.doc.tocid = dbo.toc.tocid
LEFT JOIN dbo.vol ON dbo.toc.vol_id = dbo.vol.vol_id
WHERE dbo.doc.tocid = #entryID
ORDER BY dbo.doc.pagenum`
The answer depends on how you currently retrieve data in the existing Crystal Report.
Option A: If your report data source is a "Command" (in other words you have written a SQL statement in the crystal report that retrieves the data you need), then you will want to modify that command to pull in this new information via a subquery. So for example if your current report SQL is something like "select x.* from foo as x", you would want it to be something like:
select x.*,
(SELECT dbo.vol.fixpath + '\'
+ SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),1,2) + '\'
+ SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),3,2) + '\'
+ SUBSTRING(CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2),5,2) + '\'
+ CONVERT(VARCHAR(8),CONVERT(VARBINARY(4), dbo.doc.storeid),2)
+ '.TIF' AS FullPathAndFilename
FROM dbo.doc
LEFT JOIN dbo.toc ON dbo.doc.tocid = dbo.toc.tocid
LEFT JOIN dbo.vol ON dbo.toc.vol_id = dbo.vol.vol_id
WHERE dbo.doc.tocid = x.tocid //this line joining the new SQL to all report rows
)
from foo as x;
Option B: If instead you pull your data from Crystal using the join wizard, then it would probably be best to create a new view in your database that matches the SQL you provided (minus the last 2 lines), and then join your existing main report tables to this view in the Crystal join wizard.

SQL limit for XML type

I am actually working on a large database and I am querying the following data;
My Query:
SELECT ldd.LDistCD, ldd.LDistDescPay
FROM LDetail ldd
INNER JOIN LDist ld
ON ldd.ID = ld.ID
AND ld.ID = '019458'
AND ld.LDistType = 'F'
Result:
What I am doing next, is to loop across the results (27873) in my VB codes to concatenate the data in the following format;
LDistCD + '|' + LDistDescPay
Normally that would be a very time consuming time looping through all these rows. Hence to optimise the work, I am using the following query which should already concatenate the data for me;
SELECT stuff((SELECT ',' + ldd.LddLabourDistCD + '|' + ldd.LddLabourDistDescPay
FROM LDetail ldd
INNER JOIN LDist ld
ON ldd.ID = ld.ID
AND ld.ID = 019425 AND ld.LDistType = 'F'
FOR XML
PATH ('')), 1, 1, '')
Everything is working fine except for the result, whereby some data is being truncated!! Running the last query on MS SQL Server returns the concatenate result but it is not complete. I get the impression there's a limit to the result which is being exceeded.
Can anyone help on the issue please?
Difficult for me to upload the db or the result but just to tell you that the 27873 rows, when concatenated in one string, is not fitting in the result.
The truncation you are seeing is specific to SQL Server Management Studio (SSMS). If you go to the Query menu and select Query Options..., then go to Results and then to Grid, you should see on the right side a section for "Maximum Characters Retrieved". The "Non XML data" has a max of 65,535 (which should also be the default) and the "XML data" is a drop-down with options:
1 MB
2 MB (default)
5 MB
Unlimited
Since the XML datatype can bring back more than 65,535 characters, you can convert your output to XML (this is only needed when using SSMS; client libraries should pull back the full string):
SELECT CONVERT(XML,
stuff((SELECT ',' + ldd.LddLabourDistCD + '|' + ldd.LddLabourDistDescPay
FROM LDetail ldd
INNER JOIN LDist ld
ON ldd.ID = ld.ID
AND ld.ID = 019425
AND ld.LDistType = 'F'
FOR XML PATH ('')), 1, 1, '')
)

Remove permission from public

please see snap shoot below.I was wondering why I can't remove the permission with following code. But I can remove the permission by using the GUI.
REVOKE ALL ON OBJECT::[dbo].[Table1] FROM [PUBLIC];
It tested this on SQL Server 2005, and the query works fine. However, do not expect the table Properties dialog to update automatically, not even after moving forward and back to another page, like Storage. You must close and reopen the dialog to see the modifications.
I checked this by running the following script in steps:
Source: How to list permissions for Public Role for a database in SQL Server.
grant select, insert, update on dbo.Table1 to public
GO
SELECT a.[name] + ' ' + v.[name] + ' ON ' + QuoteName(oo.[name])
+ '.' + QuoteName(o.[name]) + ' TO ' + QuoteName(u.[name])
FROM dbo.sysprotects AS p
JOIN master.dbo.spt_values AS a
ON (a.number = p.protecttype
AND 'T' = a.type)
JOIN master.dbo.spt_values AS v
ON (v.number = p.action
AND 'T' = v.type)
JOIN dbo.sysobjects AS o
ON (o.id = p.id)
JOIN dbo.sysusers AS oo
ON (oo.uid = o.uid)
JOIN dbo.sysusers AS u
ON (u.uid = p.uid)
WHERE 'public' = u.name
GO
revoke all on object::dbo.Table1 to public
GO
-- Run query again
Please note that a warning is issued when using revoke all: The ALL permission is deprecated and maintained only for compatibility. It DOES NOT imply ALL permissions defined on the entity.

Compare structures of two databases?

I wanted to ask whether it is possible to compare the complete database structure of two huge databases.
We have two databases, the one is a development database, the other a production database.
I've sometimes forgotten to make changes in to the production database, before we released some parts of our code, which results that the production database doesn't have the same structure, so if we release something we got some errors.
Is there a way to compare the two, or synchronize?
For MySQL database you can compare view and tables (column name and column type) using this query:
SET #firstDatabaseName = '[first database name]';
SET #secondDatabaseName = '[second database name]';
SELECT * FROM
(SELECT
CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
FROM information_schema.columns cl, information_schema.TABLES ss
WHERE
cl.TABLE_NAME = ss.TABLE_NAME AND
cl.TABLE_SCHEMA = #firstDatabaseName AND
ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
ORDER BY
cl.table_name ) AS t1
LEFT JOIN
(SELECT
CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
FROM information_schema.columns cl, information_schema.TABLES ss
WHERE
cl.TABLE_NAME = ss.TABLE_NAME AND
cl.TABLE_SCHEMA = #secondDatabaseName AND
ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
ORDER BY
cl.table_name ) AS t2 ON t1.tableRowType = t2.tableRowType
WHERE
t2.tableRowType IS NULL
UNION
SELECT * FROM
(SELECT
CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
FROM information_schema.columns cl, information_schema.TABLES ss
WHERE
cl.TABLE_NAME = ss.TABLE_NAME AND
cl.TABLE_SCHEMA = #firstDatabaseName AND
ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
ORDER BY
cl.table_name ) AS t1
RIGHT JOIN
(SELECT
CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
FROM information_schema.columns cl, information_schema.TABLES ss
WHERE
cl.TABLE_NAME = ss.TABLE_NAME AND
cl.TABLE_SCHEMA = #secondDatabaseName AND
ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
ORDER BY
cl.table_name ) AS t2 ON t1.tableRowType = t2.tableRowType
WHERE
t1.tableRowType IS NULL;
If you prefer using tool with UI you can also use this script
https://github.com/dlevsha/compalex
which can compare tables, views, keys etc.
Compalex is a lightweight script to compare two database schemas. It
supports MySQL, MS SQL Server and PostgreSQL.
Screenshot (compare tables)
You can use the command line:
mysqldump --skip-comments --skip-extended-insert -d --no-data -u root -p dbName1>file1.sql
mysqldump --skip-comments --skip-extended-insert -d --no-data -u root -p dbName2>file2.sql
diff file1.sql file2.sql
You can just dump them with --no-data and compare the files.
Remember to use the --lock-tables=0 option on your production database to avoid the big nasty global lock.
If you use the same mysqldump version (your dev and production systems should have the same software, right?) then you'll expect to get more-or-less identical files out. The tables will be in alpha order so a simple diff will show discrepancies up easily.
To answer this kind of question currently, I've made a script that uses information_schema content to compare column, datatype, and table
SET #database_current = '<production>';
SET #database_dev = '<development>';
-- column and datatype comparison
SELECT a.TABLE_NAME, a.COLUMN_NAME, a.DATA_TYPE, a.CHARACTER_MAXIMUM_LENGTH,
b.COLUMN_NAME, b.DATA_TYPE, b.CHARACTER_MAXIMUM_LENGTH
FROM information_schema.COLUMNS a
LEFT JOIN information_schema.COLUMNS b ON b.COLUMN_NAME = a.COLUMN_NAME
AND b.TABLE_NAME = a.TABLE_NAME
AND b.TABLE_SCHEMA = #database_current
WHERE a.TABLE_SCHEMA = #database_dev
AND (
b.COLUMN_NAME IS NULL
OR b.COLUMN_NAME != a.COLUMN_NAME
OR b.DATA_TYPE != a.DATA_TYPE
OR b.CHARACTER_MAXIMUM_LENGTH != a.CHARACTER_MAXIMUM_LENGTH
);
-- table comparison
SELECT a.TABLE_SCHEMA, a.TABLE_NAME, b.TABLE_NAME
FROM information_schema.TABLES a
LEFT JOIN information_schema.TABLES b ON b.TABLE_NAME = a.TABLE_NAME
AND b.TABLE_SCHEMA = #database_current
WHERE a.TABLE_SCHEMA = #database_dev
AND (
b.TABLE_NAME IS NULL
OR b.TABLE_NAME != a.TABLE_NAME
);
Hope this script can also help people that looks for a non-application solution, but the usage of script. Cheers
I tried mysqldiff without success, so I would like to enrich the future readers by drawing attention to mysqlworkbench's compare function. http://dev.mysql.com/doc/workbench/en/wb-database-diff-report.html#c13030
if you open a model tab, and select the databases menu, you get a compare schemas option, which you can use to compare two different schemas on two different servers, or two schemas on the same server, or a schema and a model, or a lot of other options i haven't tried yet.
For mysql on Linux, it is possible via phpmyadmin to export the databases without 'data' and only structure.
Scrolling through the export options for the entire database, just deselect 'data' and set the output to text. Export both databases you wish to compare.
Then in file compare in your preferred program / site, compare the two text file outputs of the databases. Synchronization is still manual in this solution, but this is effective for comparing and finding the structural differences.
Depending on your database, the tools available vary.
I use Embarcadero's ER/Studio for this. It has a Compare and Merge feature.
There are plenty others, such as Toad for MySQL, that also have compare. Also agree on the Red-Gate suggestion, but never used it for MySQL.
Check out Gemini Delta - SQL Difference Manager for .NET. A free beta version is available for download, but the full version is only a few days away from public release.
It doesn't compare row-level data differences, but it compares tables, functions, sprocs, etc... and it is lightning fast. (The new version, 1.4, loads and compares 1k Sprocs in under 4 seconds, compared with other tools I've tested which took over 10 seconds.)
Everyone is right though, RedGate does make great tools.

Resources