This is Sample code, the same in SQLFiddle
DECLARE #Test int
SET #Test = '6'
IF #Test > 5 PRINT N'Warning - large queries may take time'
ELSE PRINT N'Query will run normally';
GO
I have a query where the '#Test' variable can be changed to any number.
The above SQL kind of demonstrates the logic. If someone enters a number higher than 5 for example i want there to be a warning message advising the user about the larger query. Is this possible in SQL? I ran this code but it returns nothing. Am i in the right direction? thanks
Related
Apologies if this has been asked before - I've spent a couple of hours searching but not found anything that's helped.
It's quite simple really - I've been asked to create a query which includes a field that when it was set up (not by me) was created as a VARCHAR instead of an INT.
I need to do some calculations on this field, however some users have been entering text into it, so the calculations fail as it can't convert the data to an INT.
Is there anything I can add to a CASE statement to handle where there's text?
I was thinking something like the below, but don't know what the actual code is:
CASE
WHEN [Field1] IS TEXT THEN 1 ;
ELSE [Field2] as [Chose name]
END
Edit: Note that this is in MS SQL Server.
Thanks.
In SQL Server, you can use try_convert() and isnull() for this:
isnull(try_convert(int, field), 1)
try_convert() attempts you cast field to an int. When that fails, null is returned; you can trap that with isnull() and turn the result to 1 instead.
Note that this only works as long as field is not null (otherwise, you would get 1 as a result).
In SQL Server
Declare #Salary varchar(100);
Set #Salary = 50000;
Select Case when ISNUMERIC(#Salary) = 1 then 1
else 0 end as [Check]
May be this will be Helpful.
Using ssms 2012 to query a 2008R2 instance, I am trying to get a plan for a specific query using the DMVs like this:
SELECT t.text
, p.query_plan
from sys.dm_exec_query_stats qs
cross join sys.dm_exec_sql_text(qs.sql_handle) t
cross join sys.dm_exec_text_query_plan(qs.plan_handle,0,-1) p
where t.text like ...
The query plan column is getting cut off after 43,679 characters. Ending with
< /Outp
instead of
< /ShowPlanXML>
I tested this with a smaller query and the whole text was returned. The query in question is not that complex, but has a lot of columns, which may be making it a bit more verbose. Also, the value returned is not a link to the plan but just the XML in text form.
Is there a limit to what is stored in plan cache or I am doing something wrong in SSMS that it is not returning the value as a plan link in the column?
Even if the bug Aaron mentions in comments is in play here, you should be able to get around it with an SSMS tweak. You can directly cast the result of your query into the xml data type, and then return it that way.
If you're returning the XML in a grid view, go to Tools/Options/Query Results/SQL Server/Results to Grid and see what the setting for Maximum Characters Retrieved for XML data is, and bump it up to "Unlimited". This should allow you to circumvent the varchar limit.
Whoops! Wrong DMV. I needed to use dm_exec_query_plan not dm_exec_text_query_plan. That solved it - thanks for the replies.
Posting another answer as this may help someone else out in the future. There are a few approaches that I've found to work around the 43,679 character limitation in outputs displayed in Grid View as specific to this question. These approaches also work if your plan exceeds the SQL XML Data Type limit of 128 nested nodes.
The first, and arguably easiest option, is to fire up PowerShell ISE and follow the instructions outlined on this blog post by Patrick Keisler. Paste his script into the ISE editor, adjust the OFFSET values (recommended), output paths/names, and then run everything to generate the final sqlplan file.
If you don't want to use PowerShell, a kludgy TSQL method I cobbled together can also be used, as follows:
-- Quick and dirty script to output large execution plans from cache
-- Be sure to replace Plan Handle and Offset Values Below
DECLARE #query_plan_nvarmax NVARCHAR(MAX), #len_out INT, #sub_str INT = 0, #sub_end INT = 43679
DECLARE #full_query_plan TABLE
(
line INT IDENTITY(1,1),
qp_line NVARCHAR(MAX)
)
SELECT #query_plan_nvarmax = query_plan,
#len_out = LEN(query_plan)--, CAST(query_plan AS XML) as xml_query_plan
-- Usage: Get Query Offset Values From sys.dm_exec_query_stats DMV
-- sys.dm_exec_text_query_plan(plan_handle, OFFSET_START|DEFAULT, OFFSET_END|DEFAULT)
FROM sys.dm_exec_text_query_plan(0x050005005EDA4857307D56540300000001000000000000000000000000000000000000000000000000000000, 10078, 83616)
WHILE #sub_str < #len_out
BEGIN
INSERT INTO #full_query_plan (qp_line)
SELECT SUBSTRING(#query_plan_nvarmax, #sub_str, #sub_end)
SET #sub_str = #sub_end
SET #sub_end = #sub_end + 43679
IF #sub_end > #len_out
SET #sub_end = #len_out
END
-- Save Output of qp_line column to text editor and remove newline characters \r\n
-- I prefer Notepad++, but any editor will suffice then save output as a .sqlplan and open in SSMS
SELECT *
FROM #full_query_plan
Take note, you'll need to edit the output of the query in an external text editor to remove the newline characters \r\n and save the result as a .sqlplan file.
I have big SQL query like this:
Select Distinct [Student].[Class].roll_nbr as [PERIOD-NBR],[Student].[Class].ent_nbr as [CLASS-NBR],
IsNull(Stuff((SELECT CAST(', ' AS Varchar(MAX)) + CAST([Student].[Subject].ent_nbr AS Varchar(MAX))
FROM [Student].[Subject]
WHERE [Student].[Subject].roll_nbr = [Student].[Class].roll_nbr
and ([Student].[Subject].class_nbr = [Student].[Class].roll_assignment_nbr
or ([Student].[Class].roll_assignment_nbr = '0'
and [Student].[Subject].class_nbr = [Student].[School].bus_stop) )
AND [Student].[Subject].ent_nbr <> ''
FOR XML PATH ('')), 1, 2, ''), '')
AS [OLD-STUDENT-NBR.OLD],IsNull(Stuff((SELECT CAST(', ' AS Varchar(MAX)) + ....
It goes on and on and a page long query, which builds a report. The problem I am having is some variable is erring out with message:
Error converting data type varchar to numeric.
This is very generic error does not tell me which variable. Is there any way to pinpoint which variable is erring out in sql 2008?
Comment out half the columns, if the error continues, comment out another half. If the error stops, it's in the section you just commented out. Rinse-repeat.
When faced with this type of error in the past, I've narrowed it down by commenting out portions of the query, see if it executes, then uncomment portions of the query until it point right to the error.
Not that I know of. However, you could try the following procedure:
1) Identify what columns are being converted.
2) Execute the select with half of them. If it executes well, then the problem is in the other half.
3) Repeat 2 (halving the number of columns) until you have come to a single candidate.
If query execution is long, keep track of all combinations tried and their result, as the problem could be affecting more than one column. This leads to:
4) If the problem continues, then there is a second affected column. Discard all columns present in queries that have executed without problem, plus the incorrect one just discovered, and start again with this set on 2).
5) Repeat until the original query (and necessary modifications) executes with no issue.
In Microsoft SQL Server 2008, I have a table, say myTable, containing about 600k rows (actually, it is a result of joining several other tables, but i suppose this is not important). One of its columns, say value is of type numeric(6,2).
The simple query SELECT value FROM myTable ORDER BY value returns of course about 600k numbers, starting with 1.01 (i.e. the lowest) and ending with 70.00 (highest); no NULLs or other values.
Please notice, that all these values are numeric and positive. However, when calling SELECT LOG(value) FROM myTable, i obtain an error message "An invalid floating point operation occurred".
This error always appears after about 3 minutes of the query running. When copying the 600k values to Excel and counting their LN(), there is absolutely no problem.
I have tried converting value to real or float, which did not help at all. Finally I found a workaround: SELECT LOG(CASE WHEN value>0 THEN value ELSE 1 END) FROM myTable. This works. But why, when all the values are positive? I have tried to take the result and compare the logarithms with those counted by Excel - they are all the same (only differences of the order 10^(-15) or smaller occured in some rows, which is almost surely given by different accuracy). That means that the condition in the CASE statement is always true, I suppose.
Does anyone have any idea why this error occurs? Any help appreciated. Thanks.
You can identify the specific value that's causing the prob;
declare #f numeric(6,2), #r float
begin try select
#f = value, #r = LOG(value)
from mytable
end try begin catch
select error_message(),'value=',#f
end catch
You would get this error - "An invalid floating point operation occurred" when you do LOG(0). The value of LOG(zero) is indeterminate in the world of Maths, hence the error.
Cheers.
If you have 100 occurrences of "PRINT" in your stored procedure, is there a nice way to turn them all on/off when debugging an non-debugging?
I could add a variable #isdebug = 1
and later on, do something like
IF #isdebug = 1 PRINT #yourvar
and then just set the #isdebug to 0 or 1 depending on what you need.
Is there a nicer way to do this?
Nope, that is also what I have in procs
IF #debug = 1
BEGIN
print 'Something'
--or insert into a log table if you need the rows of a temp table
--or the results of a calculation
END
An expansion of this idea is to setup up a controlling string. This giving us more options rather than either on or off.
For example:
Stored procedure parameter declaration
(#Debug varchar(5), -- use bit wise control for debugging, currently 5 levels.
Simple substring to drive a testing/debug block.
if substring(#Debug, 1, 1) = '1'
For a test run you could enter '10001' for #Debug so that "level" 1 debugs show (ie initialisations) and only "level" 5 debugs show for the sub-section of code you are testing/debugging.
You could expand on this idea by using number values (ie 2-9) too. But that might be too over the top.