Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
Author |
Topic |
Kristen
Test
22859 Posts |
Posted - 2011-10-28 : 11:55:08
|
I'm fed up with QUOTED_IDENTIFIER accidentally getting set to OFF.We don't have a SET QUOTED_IDENTIFIER ON in every single Sproc create script that we have, and I don't want to clutter them up by putting it there.Is there a way that I can detecting if QUOTED_IDENTIFIER is OFF? All our scripts run an Sproc that logs the version of the script being run, and I could put the test into that so I at least get a warning when this happens.I've looked in BoL, but obviously not in the right place Thanks. |
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2011-10-28 : 11:59:05
|
Look at the SESSIONPROPERTY() function. I wrote about another method here:http://weblogs.sqlteam.com/robv/archive/2010/09/22/handy-sql-server-function-you-may-not-have-known-about.aspx |
 |
|
Kristen
Test
22859 Posts |
Posted - 2011-10-28 : 12:09:51
|
Perfect! Many thanks Rob. Here's what I have so far:SELECT *FROM( SELECT name, [Status] = CASE WHEN (@@OPTIONS & number) = 0 THEN 'OFF' ELSE 'ON' END FROM master.dbo.spt_values WHERE type='SOP' AND number > 0) AS XWHERE ( ([name]='ansi_null_dflt_off' AND [Status] <> 'OFF') OR ([name]='ansi_null_dflt_on' AND [Status] <> 'ON') OR ([name]='ansi_nulls' AND [Status] <> 'ON') OR ([name]='ansi_padding' AND [Status] <> 'ON') OR ([name]='ansi_warnings' AND [Status] <> 'ON') OR ([name]='arithabort' AND [Status] <> 'ON') OR ([name]='arithignore' AND [Status] <> 'OFF') OR ([name]='concat_null_yields_null' AND [Status] <> 'ON') OR ([name]='cursor_close_on_commit' AND [Status] <> 'OFF') OR ([name]='disable_def_cnst_check' AND [Status] <> 'OFF') OR ([name]='implicit_transactions' AND [Status] <> 'OFF') OR ([name]='nocount' AND [Status] <> 'OFF') OR ([name]='numeric_roundabort' AND [Status] <> 'OFF') OR ([name]='quoted_identifier' AND [Status] <> 'ON') OR ([name]='xact_abort' AND [Status] <> 'OFF') )--ORDER BY [name] |
 |
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2011-10-28 : 12:52:12
|
Keep in mind that QUOTED_IDENTIFIER is a setting on the procedure declaration, not just a statement within its body. (In fact SET QUOTED_IDENTIFIER should not appear in a procedure body, as its effects can be detrimental)You can determine which procedures do not have that setting with the following:select OBJECT_NAME(object_id), * from sys.sql_modules where uses_quoted_identifier=0Once you find them, you can reset QUOTED_IDENTIFIER and use ALTER PROCEDURE to recreate them with the correct settings.Another best practice is to remove all double quotes from your code, ensure strings are delimited only with single quotes, and (optionally) delimit all object identifiers with square brackets. Yeah it's a lot of work, but doing so renders the QUOTED_IDENTIFIER setting moot. |
 |
|
X002548
Not Just a Number
15586 Posts |
|
Kristen
Test
22859 Posts |
Posted - 2011-10-28 : 14:25:50
|
quote: Originally posted by robvolk Keep in mind that QUOTED_IDENTIFIER is a setting on the procedure declaration, not just a statement within its body. (In fact SET QUOTED_IDENTIFIER should not appear in a procedure body, as its effects can be detrimental)
Yeah, been-there and done-that. And I now find that my euphoria is slightly sort-lived. I'll knock up an example shortly.quote: You can determine which procedures do not have that setting with the following:
Yup, done that too ... it was my first action when I discovered that we had a problem. About 50% of the Sprocs are wrong-QUOTED_IDENTIFIER, but it varies from DB to DB (probably according to what something else set at the time that the rollout scripts were run  quote: Another best practice is to remove all double quotes from your code, ensure strings are delimited only with single quotes, and (optionally) delimit all object identifiers with square brackets. Yeah it's a lot of work, but doing so renders the QUOTED_IDENTIFIER setting moot.
and that's my final annoyance. We did this years ago, so we have (as far as I know) none of these issues in our code, in practice. However, we have recently introduced some indexed views, to improve performance in some areas, and now Sprocs that were created with QUOTED_IDENTIFER OFF give error when run.We can fix that at the next rollout by re-creating EVERY Sproc (which is a PITA as that will take a long time to run the script, and 99% of them won't actually have changed materially. Or we could custom-build rollout scripts to only have specific SProcs in them, but I can't even be sure that TEST and PRODUCTION DBs are the same in this regard, and I don't really want to have custom rollout scripts for each Client/Database as that is a "hybrid" method of working compared to our carefully crafted, tested and rehearsed "only this has changed since last time" rollout process, so it runs the risk that we trip over some other never-before-seen issue compared to doing it "how we always do".As a knee-jerk reaction our rollout scripts now have a SET-the-whole-world at the top that guarantees there are no mavericks - but, even then, we might have a script in the middle that was generated with SSMS that has prefixed the script with a helpful SET QUOTED_IDENTIFIER ON but then cavalierly added a SET QUOTED_IDENTIFIER OFF to the end of the script, creating a train-wreck for the rest of the concatenated rollout script.So ... because each of our scripts, that we concatenate to make the master-rollout-script, has a "Log this NAME and VERSION" Sproc call I thought adding a check for all the correct SET values (to the "log this" Sproc) would mean that at least we would get an alert when the wrong SETting was in place. |
 |
|
Kristen
Test
22859 Posts |
Posted - 2011-10-28 : 14:56:32
|
I don't seem to be able to detect some values, e.g. QUOTED_IDENTIFIER, within an Sproc:--IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = 'Test_SET_Values') DROP PROCEDURE dbo.Test_SET_ValuesGOCREATE PROCEDURE dbo.Test_SET_ValuesAS/* * Test_SET_Values Test SET values are set to Default Values * */DECLARE @intOPTIONS intSELECT @intOPTIONS = @@OPTIONS -- Store current valueSET NOCOUNT ONSET XACT_ABORT ONSET ARITHABORT ONDECLARE @intRetVal int -- Return valueSELECT @intRetVal = 0 -- Assume no error-- ... all sorts of code removed ... SELECT * INTO #Test_SET_Values_01 FROM ( SELECT name, [Status] = CASE WHEN (@intOPTIONS & number) = 0 THEN 'OFF' ELSE 'ON' END FROM master.dbo.spt_values WHERE type='SOP' AND number > 0 ) AS X WHERE ( ([name]='ansi_null_dflt_off' AND [Status] <> 'OFF') OR ([name]='ansi_null_dflt_on' AND [Status] <> 'ON') OR ([name]='ansi_nulls' AND [Status] <> 'ON') OR ([name]='ansi_padding' AND [Status] <> 'ON') OR ([name]='ansi_warnings' AND [Status] <> 'ON') OR ([name]='arithabort' AND [Status] <> 'ON') OR ([name]='arithignore' AND [Status] <> 'OFF') OR ([name]='concat_null_yields_null' AND [Status] <> 'ON') OR ([name]='cursor_close_on_commit' AND [Status] <> 'OFF') OR ([name]='disable_def_cnst_check' AND [Status] <> 'OFF') OR ([name]='implicit_transactions' AND [Status] <> 'OFF') OR ([name]='nocount' AND [Status] <> 'OFF') OR ([name]='numeric_roundabort' AND [Status] <> 'OFF') OR ([name]='quoted_identifier' AND [Status] <> 'ON') OR ([name]='xact_abort' AND [Status] <> 'OFF') ) -- ORDER BY [name] IF @@ROWCOUNT <> 0 BEGIN SELECT [Error] = '****** WARNING: Unexpected SET values ******' SELECT [name], [Status] FROM #Test_SET_Values_01 ORDER BY [name] END DROP TABLE #Test_SET_Values_01-- ... more code removed ... SET NOCOUNT OFF RETURN @intRetValGO-- TEST RIG-- Set all properties to inappropriate valuesSET ansi_null_dflt_off ONSET ansi_null_dflt_on OFFSET ansi_nulls OFFSET ansi_padding OFFSET ansi_warnings OFFSET arithabort OFFSET arithignore ONSET concat_null_yields_null OFFSET cursor_close_on_commit ON-- SET disable_def_cnst_check ONSET implicit_transactions ONSET nocount ONSET numeric_roundabort ONSET quoted_identifier OFFSET xact_abort ONGOEXEC dbo.Test_SET_ValuesGO-- Reinstate appropriate valuesSET ansi_null_dflt_off OFFSET ansi_null_dflt_on ONSET ansi_nulls ONSET ansi_padding ONSET ansi_warnings ONSET arithabort ONSET arithignore OFFSET concat_null_yields_null ONSET cursor_close_on_commit OFF-- SET disable_def_cnst_check OFFSET implicit_transactions OFFSET nocount OFFSET numeric_roundabort OFFSET quoted_identifier ONSET xact_abort OFFGO |
 |
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2011-10-28 : 15:01:14
|
Ahhhh yeah, indexed views. You can mitigate some of the pain by making all the database settings consistent, and making sure all your devs have consistent settings.Then my next suggestion is....source control. Never build or deploy ANYTHING that doesn't come out of source control, and preferably from an automated build process.If source control's not feasible, at least use a consistent method, i.e. SSMS only, or custom deployment only. Mixing SSMS scripts with scripts from other sources is really painful because the script output is not consistent. I filed a Connect item with MS about it but they closed it:https://connect.microsoft.com/SQLServer/feedback/details/583013/provide-consistent-database-script-output-across-all-microsoft-products#One last thing you might want to consider is a DDL and/or Logon trigger that can detect invalid settings and roll back the event. So if someone logs on with the wrong setting they're disconnected (not sure this will work). You can also query sys.dm_exec_sessions for some of the settings on existing connections, and possibly kill them. |
 |
|
X002548
Not Just a Number
15586 Posts |
|
|
|
|
|
|