Delete all service broker message types - sql-server

Currently I am using:
SELECT * FROM sys.service_message_types
to list service broker message types. However, how would I go about deleting all message types?

Below is an example that drops all user message types in the current database, using the model database as a reference to exclude system message types.
Note the DROP will fail if contracts use the type. Contracts bound to the type and indirectly referencing SB objects (i.e. services) will need to be dropped first.
DECLARE #SQL nvarchar(MAX);
SELECT #SQL = STRING_AGG(N'DROP MESSAGE TYPE ' + QUOTENAME(current_db.name), ';')
FROM sys.service_message_types AS current_db
LEFT JOIN model.sys.service_message_types AS model_db ON
model_db.message_type_id = current_db.message_type_id
WHERE model_db.message_type_id IS NULL;
EXECUTE sp_executesql #SQL;

Related

SQL Server Syntax failure

I am running the following code and I am getting a syntax error near '.TableReference' error, the code use to work then I did something and now I have this error and I can't seem to find the issue
Through troubleshooting I have narrowed the code issue to the ' FROM ' + #TableName section but it appears to be good code.
BEGIN
--SET NOCOUNT ON;
DECLARE #TableName AS NVARCHAR(MAX) --The Fully qualified database name
DECLARE #Ref AS NVARCHAR(MAX) --The name of the Table we are processing
DECLARE #TempTab AS NVARCHAR(MAX) --the temporary table we are subjecting to the tortures of this process
DECLARE #TempQuery AS NVARCHAR(MAX) --Query to move all data into the temporary table
--This selects the first record in the Website Request Table which hasn't been processed and passes it into the TempTab variable
SET #NDTRef = (SELECT TOP 1 Reference from dbo.WebRequestTable Where Processing IS NULL)
SET #TableName = 'Processing.dbo.'+#NDTRef
Set #TempTab = 'TEMP' + #NDTRef
SET #TempQuery = 'SELECT * INTO '+ #TempTab +' FROM ' + #TableName
EXEC sp_sqlexec #TempQuery;
END
Any help would be appreciated it is a stand alone instance of SQL Server 2019 and the code is a part of a stored procedure but the rest of the code runs off the temporary table created in this block
After suggestions I put in a print statement regarding the #TempQuery when put straight after and the EXEC removed the output is
SELECT * INTO TEMP2294690 FROM Processing.dbo.2294690
With the EXEC back in play I get the error
Msg 102, Level 15, State 1, Line 17 Incorrect syntax near '.2294690'.
The print output after the EXEC shows:
SELECT * INTO TEMP2294690 FROM Processing.dbo.2294690
The Table 2294690 exists in the database Processing the Temp2294690 is a table that should be created by this block but it isn't being created
In SQL Server, regular Identifiers must begin with a letter, an underscore (_), at sign (#) or the number sigh (#).
(There are other rules as well, but this is the one relevant to the question...)
Identifiers that don't follow the rules of regular identifiers can be only used if they are enclosed in square brackets ([]) or double quotation marks (").
The best way to handle identifiers when creating dynamic SQL statements is to use the built in QUOTENAME function - this way you can make sure your query doesn't break even if the identifier doesn't follow the rules of regular identifiers.
So your SQL should look like this:
SET #TableName = '[Processing].[dbo].'+ QUOTENAME(#NDTRef)
SET #TempTab = 'TEMP' + #NDTRef
SET #TempQuery = 'SELECT * INTO '+ QUOTENAME(#TempTab) +' FROM ' + #TableName
That being said, you should also probably check my blog post entitled The do’s and don’ts of dynamic SQL for SQL Server where you can find some more information about how to safely create dynamic SQL.
You know that if the view is temporary only you can see it and if you close your session user the view is deleted and dont save try with create view dont temp and drop after you read.
If all previus you have it in your mind you could try this for see if the view has created --> its a extract of Microsoft official pagge:
VIEW_METADATA
Specifying the instance of SQL Server will return the DB-Library, ODBC, and OLE DB APIs the metadata information about the view instead of the base tables when you request the browse mode metadata for a query that references the view. Browse mode metadata is additional metadata that the SQL Server instance returns to these client-side APIs. This metadata enables client-side APIs to implement updateable client-side cursors. Browse mode metadata includes information about the base table to which the columns in the result set belong.

Pass Linked Server name as parameter to Stored Procedure (not using Dynamic TSQL)

I need to pass linked server name as variable to stored procedure right now after testing and research they all suggest to using dynamic sql and open query which I am using now. however I am not comfortable using it(sql injection) plus I need to call other user defined function to the query. I am looking for a more secure and direct call. Here is my SP
ALTER PROCEDURE [dbo].[GetBackUpStatus]
-- Add the parameters for the stored procedure here
#linkedServerName AS VARCHAR(100),
#exemptDB as VARCHAR(100)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
DECLARE #Sql varchar(8000)
SET NOCOUNT ON;
set #Sql = 'select * from openquery (' + #linkedServerName + ' , ''SELECT SERVERPROPERTY(''''SERVERNAME'''') AS "SERVERNAME",
T1.NAME AS DatabaseName,
MAX(T2.backup_finish_date) AS last_db_backup_date,
CAST(COALESCE(DATEDIFF(second, MAX(T2.backup_finish_date) , CURRENT_TIMESTAMP)/ 3600.0, 9999.0) as NUMERIC(6,2)) AS [Hours Since Backup]
FROM master.sys.databases T1
LEFT OUTER JOIN msdb.dbo.backupset T2 ON T2.database_name = T1.NAME
WHERE T1.NAME NOT IN (''''tempdb'''')
GROUP BY T1.NAME
ORDER BY T1.NAME'')'
Exec (#Sql)
END
the purpose of this query is to get the server status and its database, I don't like this because of that confusing single quotes, this query will eventually grow as I develop and add function calls.
I tried this and something like this is what I wanted, since it is direct query and cleaner without those quotes. That's how I typically use linked server.
Select * from [' + #linkedservername + '].[schema].table
thanks
Solution for a large scale data model with hundreds of tables / objects.
Dynamic modification and cloning of a stored procedure for every linked-server.
It is kinda hiding any dynamic SQL under the hood.
How to
Create a stored procedure which interacts with an existing linked-server.
During a database deployment process:
Obtain the source code of the stored procedure.
Replace the name of the linked-server in the code.
If you want to create a new stored procedure (cloned), replace the name of the initial stored procedure in the code.
Create a cloned stored procedure or modify the current.
Repeat all steps for each required linked-server.
There are another variations for it.
Now, any external logic may decide which procedure to use.
You can check the existence of a linked-server or its related stored procedure.
For modifications and cloning, it is possible to use SQL Server or external tools, such as C#, CMD, etc.
For creation under SQL Server.

Is there any virtue of synonym for Table or View over using a VIEW?

For decades i've used VIEWs as a synonym:
CREATE VIEW dbo.Banks AS
SELECT *
FROM OtherDatabase.dbo.Banks
i do this so i can abstract where the "real" table is. And when it changes, it's as simple as altering the view:
And this works well. It's doesn't cause the optimizer any issues, and i have been able to edit the view as required.
Synonyms
Starting with SQL Server 2005, Microsoft introduced synonyms:
CREATE SYNONYM dbo.Banks FOR OtherDatabase.dbo.Banks
It seems to work identically to the VIEW approach. Every execution plan i've looked at behaves identically.
Unfortunately it seems that synonyms are unable to provide one of their basic functions, functionality i need:
Provides a layer of abstraction that protects a client application from changes made to the name or location of the base object
You are not able to change where a synonym points. Because there is no ALTER SYNONYM statement, you first have to drop the synonym and then re-create the synonym with the same name, but point the synonym to the new location.
Do they have any redeeming quality?
Practically speaking, this isn't going to happen. i will just never do it. i won't use a mechanism that requires me to drop objects from a database in order to change a setting. i'm certainly not going to delete all the easily alterable VIEWs, replacing them with SYNONYMs, and have to explain to everyone why making everything harder is "better".
So my question is, is there anything i am losing by using views?
every execution plan looks identical to synonyms
i can easily change the "view synonym" at any time
Is there a virtue to a table or view synonym that i'm missing?
Aside from having to call RefreshAllViews in case i forgot that i made a table change somewhere
Even stored procedures
i don't even use synonyms for stored procedures:
CREATE PROCEDURE dbo.GetUSDNoonRateAsOf #tradeDate datetime AS
EXECUTE OtherDatabase.dbo.GetUSDNoonRateAsOf #tradeDate
Is there a value in synonyms that i am missing?
Update: RefreshAllViews procedure
We have a standard procedure in every database. Reordering, or inserting, columns wreaks havoc on views; so they have to be "refreshed".
CREATE PROCEDURE [dbo].[RefreshAllViews] AS
-- This sp will refresh all views in the catalog.
-- It enumerates all views, and runs sp_refreshview for each of them
SET NOCOUNT ON
DECLARE abc CURSOR FOR
SELECT TABLE_NAME AS ViewName
FROM INFORMATION_SCHEMA.VIEWS
ORDER BY newid()
OPEN abc
DECLARE #ViewName varchar(128)
--DECLARE #ParmDefinition NVARCHAR(500)
-- Build select string once
DECLARE #SQLString nvarchar(2048)
--SET #SQLString = N'EXECUTE sp_RefreshView #View'
--SET #ParmDefinition = N'#View nvarchar(128)'
FETCH NEXT FROM abc
INTO #ViewName
WHILE ##FETCH_STATUS = 0
BEGIN
IF #ViewName <> 'IndexServerNodes'
BEGIN
SET #SQLString = 'EXECUTE sp_RefreshView '+#ViewName
PRINT #SQLString
EXECUTE sp_ExecuteSQL #SQLString--, #ParmDefinition, #View = #ViewName
END
FETCH NEXT FROM abc
INTO #ViewName
END
CLOSE abc
DEALLOCATE abc
God knows why SQL Server doesn't do it for me.
A synonym is a much more transparent redirect. I prefer them over views because views need to be maintained. When you use SELECT * especially.
I'm not sure I buy that the lack of ALTER SYNONYM is a real blocker. The drop/create of a synonym is a very simple metadata operation, and will be very fast. Omitting error handling for brevity:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
DROP SYNONYM ...
CREATE SYNONYM ...
COMMIT TRANSACTION;
Similarly, for stored procedures, if your base stored procedure interface changes (say, you add a parameter), you have to also change the wrapper procedure - not so with a synonym.
One downside is that you can create, say, an instead of trigger on a view, but you can't on a synonym. There are other operations you can't perform via a synonym (mostly DDL). And of course IntelliSense may not function correctly, depending on version.
Not being able to memorize the syntax seems like a made-up excuse to me. There are no fancy options or with clauses; just a 2-part name for the synonym, and a 2-, 3- or 4-part name for the object it refers to:
CREATE SYNONYM dbo.Something FOR Server.Database.dbo.SomethingElse;
If you can't memorize that, how did you create the synonym in the first place?
I also have a suggestion to thoroughly simplify your stored procedure (and prevent it from failing when any view is not in the dbo schema, or the procedure is executed by someone whose default schema is not the same as the view's schema, or the view has an ' or space in its name, or otherwise breaks any of the rules for identifiers (you can find them on this page)):
CREATE PROCEDURE [dbo].[RefreshAllViews]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX) = N'';
SELECT #sql += '
EXEC sp_refreshview ' + CHAR(39)
+ QUOTENAME(REPLACE(s.name,'''',''''''))
+ '.' + QUOTENAME(REPLACE(v.name,'''','''''')) + CHAR(39) + ';'
FROM sys.views AS v
INNER JOIN sys.schemas AS s
ON v.[schema_id] = s.[schema_id];
PRINT #sql;
EXEC sp_executesql #sql;
END
GO
At the very least, if you're going to keep the cursor, stop using the terrible default options (declare the cursor as LOCAL FAST_FORWARD), and use sys.views instead of INFORMATION_SCHEMA.
God knows why SQL Server doesn't do it for me.
Because SQL Server is software, and it isn't perfect - especially when it comes to dependencies. The main problem is that you are violating a best practice by using SELECT * in your views in the first place. shrug If you would accept your hang-ups about synonyms, you won't have to worry about that.
If a view references a table, and you subsequently add columns to that table, you must modify the view in order to “pick up” the new column—even if you use SELECT *. Synonyms will “pick up” those columns automatically. Here’s a sample script:
-- Set things up
CREATE TABLE Foo
(
Id int not null
,data varchar(10) not null
)
GO
INSERT Foo values (1,'one'),(2,'Two')
GO
CREATE SYNONYM synFoo for Foo
GO
CREATE VIEW vFooDelim as select Id, Data from Foo
GO
CREATE VIEW vFooStar as select * from Foo
GO
select * from Foo
select * from synFoo
select * from vFooDelim
select * from vFooStar
then,
-- Add a column
ALTER TABLE Foo
add MoreData datetime default getdate()
GO
select * from Foo
select * from synFoo
select * from vFooDelim
select * from vFooStar
GO
(don’t forget to)
-- Clean things up
DROP Synonym synFoo
DROP VIEW vFooDelim
DROP VIEW vFooStar
DROP TABLE Foo
A significantly more obscure situation (that we do all the time here), if you have to set up a reference in a database to an object in another database, you don’t necessarily know what columns are in that table (dynamic denormalized) are or will be, and you don’t know the name of the database at the time you write your code (one database per client, but only once they sign the contract) (usually), using synonyms can be a godsend. At the time of database creation, just dynamicaly build and run CREATE SYNONYM myTable FOR <DatabaseName>.<schema>.MyTable, and you are done—no matter what columns get added for which client in the future.
Synonyms are useful for situations where you're working with lots of disparate data sources/multiple databases etc, or doing data migrations.
I've never really found cause to use them in new, greenfield developments.

Remove user name from table name

I restored a database after a server failure and now I'm running into a problem where the table names show as database_user_name.table_name. So when I query something like:
select * from contacts
it doesn't work because it expects it be fully qualified, as in:
select * from user1000.contacts
The problem with this is that I have hundreds of stored procedures that reference the tables with their name, so none of the queries work.
Is there a way to tell SQL Server 2005 to drop the username from the table without changing the user as the owner?
try this advice from the manual:
To change the schema of a table or view by using SQL Server Management Studio, in Object Explorer, right-click the table or view and then click Design. Press F4 to open the Properties window. In the Schema box, select a new schema.
If you are sure none of the tables exist in the dbo schema as well, then you can say:
ALTER SCHEMA dbo TRANSFER user1000.contacts;
To generate a set of scripts for all of the tables in that schema, you can say:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'
ALTER SCHEMA dbo TRANSFER user1000.' + QUOTENAME(name) + ';'
FROM sys.tables
WHERE SCHEMA_NAME([schema_id]) = N'user1000';
PRINT #sql;
--EXEC sp_executesql #sql;
(Once you're happy with the PRINT output - acknowledging that it will be truncated at 8K even though the variable really contains the whole script - uncomment the EXEC and run it again. This does not check for potential conflicts.)
But the real fix is to fix your code. You should never say select * from contacts - both the * and the missing schema prefix can be problematic for various reasons.

Multiple websites that uses same database structure

I have three websites which uses an abstract database structure with tables like: Items, Places, Categories, etc... and stored procedures like GetItemsByCategory, GetRelatedItems, etc... Actually im using exactly the same database structure for these 3 different websites.
From a code perspective im using the same code for all websites (except the HTML which is specific foreach one), and all the common code is in few projects used by all websites, so everytime that i detect a bug (which is in all websites) i just fix it on one place (the common part used by all) and automatically all websites get the fix.
Actually im using Asp.net MVC3 and Sql server.
Everytime i want to extend some funcionality, and i need a new table, stored procedure or something related with database, i have to do the modification in each database.
Do you know any approach that i could use to be able to have the same flexibility and do database modifications only one time for all websites?
Do you think I'm using a good approach or i should use something different in your opinion?
If the databases are on a single server, you could generate the script for the procedure from Management Studio, and make sure to use the option to "check for object existence" (Tools > Options > SQL Server Object Explorer > Scripting). This will yield something like this (most importantly it produces your stored procedure code as something you can execute using dynamic SQL):
USE DBName;
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
IF NOT EXISTS (...)
BEGIN
EXEC dbo.sp_executesql #statement = N'CREATE PROCEDURE dbo.whatever ...
'
END
GO
Now that you have this script, you can modify it to work across multiple databases - you just need to swipe the #statement = portion and re-use it. First you need to stuff the databases where you want this to work into a #table variable (or you can put this in a permanent table, if you want). Then you can build a command to execute in each database, e.g.
DECLARE #dbs TABLE (name SYSNAME);
INSERT #dbs(name) SELECT N'db1';
INSERT #dbs(name) SELECT N'db2';
INSERT #dbs(name) SELECT N'db3';
-- now here is where we re-use the create / alter procedure command from above:
DECLARE #statement NVARCHAR(MAX) = N'CREATE PROCEDURE dbo.whatever ...
';
-- now let's build some dynamic SQL and run it!
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + '
EXEC ' + QUOTENAME(name) + '.dbo.sp_executesql N''' + #statement + ''';'
FROM #dbs;
EXEC sys.sp_executesql #sql;
Alternatively, you could create a custom version of my sp_msforeachdb or sp_ineachdb replacements:
Making a more reliable and flexible sp_MSforeachdb
Execute a Command in the Context of Each Database in SQL Server
I used to use a tool called SQLFarms Combine for this, but the tool doesn't seem to exist anymore, or perhaps it has been swallowed up / re-branded by another company. Red Gate has since produced SQL Multi Script that has similar functionality.
If you added a column to all your tables called websiteId you could just have one database. Store the unique websiteId in each site's web.config and just pass it with each request for data. Obviously each site's data is stored with their websiteId so data can be queried per website.
It means a bit of refactoring in your db and any calls to your your db, but once done, you only have one database to maintain.
Of course this is assuming your databases are on the same server...

Resources