Sybase: how to show the values of the current session variables? - sybase

I can do for example:
> set chained on
But how can I see the current value of chained, or all current session variables?

Take a look at this list of ASE global variables.
For the current chained status: select ##tranchained:
returns 0 if chained mode is disabled (set chained off)
returns 1 if chained mode is enabled (set chained on )

Related

How to add a running to Redis?

From several servers I would like to add keys like doc:1 and then doc:2 etc.
Now in order that the different servers do not try to add to, say, doc:2 at the same time, I thought there is some mechanism like "add to doc:{index}" and the index gets automatically bumped.
Is there some way to make that work?
You could use a distributed lock and have the winner write
for each server, attempt to acquire lock until success
on acquire lock
read numeric value
increment
write
release lock
docs
https://redis.io/docs/manual/patterns/distributed-locks/
https://redis.io/commands/incr/
You could use a key which you increment on every addition: the INCR command does just that, atomically, and returns the incremented value which you can use to generate the new key name.
> INCR counter
42
> SET doc:42 foobar
OK
Update: in the event you want the whole set of operations (incrementing the counter and setting the value) to be atomic, you can execute a Lua script instead:
> EVAL "local value = redis.call('INCR', 'counter'); redis.call('SET', 'doc:'..value, ARGV[1])" 0 foobar
(nil)
Explanation:
local value = redis.call('INCR', 'counter');
Execute INCR counter and store the result in the value variable.
redis.call('SET', 'doc:'..value, ARGV[1]);
Execute SET against the key named after the concatenation of doc: and the value variable using the data passed through the first EVAL argument - in our case foobar.
Finally, should you need to return the incremented counter value to the caller just append a final return value; block to the script.

How to find out every time a stored procedure has run

Is there a way to find out every single time a stored procedure has run in the last X amount of days? There are ways to see the last time it ran, but what if I want to see the last X number of times.
I can't find anything when I searched. Any suggestions?
I would suggest that you take advantage of the ability of Extended Events to capture a histogram. You can set it up like this:
CREATE EVENT SESSION [ProcedureExecutionCount]
ON SERVER
ADD EVENT sqlserver.rpc_completed
(SET collect_statement = (0)
WHERE (
[sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name], N'AdventureWorks')
AND [object_name] = N'AddressByCity'
)
)
ADD TARGET package0.histogram
(SET filtering_event_name = N'sqlserver.rpc_completed', source = N'object_name', source_type = (0));
That will now, only, ever, count the number of times that procedure, on that database, is executed. Nice, simple, clean and easy.
There are several ways to do it. Visit here: https://www.mssqltips.com/sqlservertip/3259/several-methods-to-collect-sql-server-stored-procedure-execution-history/

Updating the xml data nodes by passing the SQL variable

I have the following XML and I need to update the specified one based on the parameter:
<DOPremium>
<BasePremium>337500</BasePremium>
<TotalPremium>337500</TotalPremium>
<NettPremium>337500</NettPremium>
<GrossPremium>337500</GrossPremium>
<OptionId>0</OptionId>
</DOPremium>
<DOPremium>
<BasePremium>337500</BasePremium>
<TotalPremium>337500</TotalPremium>
<NettPremium>337500</NettPremium>
<GrossPremium>337500</GrossPremium>
<OptionId>1</OptionId>
</DOPremium>
<DOPremium>
<BasePremium>337500</BasePremium>
<TotalPremium>337500</TotalPremium>
<NettPremium>337500</NettPremium>
<GrossPremium>337500</GrossPremium>
<OptionId>2</OptionId>
</DOPremium>
I'm trying to update the respective nodes based on the selection of the DOPremium object, but I'm not able to do that. Can someone verify where I'm wrong?
SET #NewXmlValue = N' <BasePremium>[sql:variable("#R15_premium")]</BasePremium>'
SET #DataXml.modify('delete /*/Premiums/DOPremium/BasePremium[sql:variable("#OptionID")]')
SET #DataXml.modify('insert sql:variable("#NewXmlValue") into (/*/Premiums/DOPremium[sql:variable("#OptionID")])[1]')
-- Add TotalPremium
SET #NewXmlValue = N' <TotalPremium>[sql:variable("#R15_premium")]</TotalPremium>'
SET #DataXml.modify('delete /*/Premiums/DOPremium/TotalPremium[sql:variable("#OptionID")]')
SET #DataXml.modify('insert sql:variable("#NewXmlValue") into (/*/Premiums/DOPremium[sql:variable("#OptionID")])[1]')
OK, first of all, this can't work:
SET #NewXmlValue = N'<BasePremium>[sql:variable("#R15_premium")]</BasePremium>'
sql:variable() is only interpreted as a function in an XQuery operation. This isn't an XQuery operation, so it will just textually insert sql:variable(...). If you want an actual XML node with the text value of the variable, you have to be a little more roundabout:
SET #NewXmlValue = '';
SET #NewXmlValue = (SELECT #NewXmlValue.query('<BasePremium>{sql:variable("#R15_premium")}</BasePremium>'));
This approach (and others) can be found in the docs. (In this very simple case concatenating the strings in T-SQL also works, of course, but in general that's not a good idea because it doesn't take care of escaping the XML when necessary.)
The syntax for selecting the desired DOPremium node also needs work -- /BasePremium[sql:variable("#OptionID")] is legal, but it means "the BasePremium node that, sequentially numbering from 1, has number #OptionID". If #OptionID is supposed to match what's in OptionID, that's not the way to write it.
If your intent was to write "change the contents of the BasePremium value of the node with OptionID text equal to #OptionID to the value #R15_premium", here's how you do that (well, one way to do that):
SET #DataXml.modify('
replace value of (
/*
/Premiums
/DOPremium[child::OptionId/.=sql:variable("#OptionID")]
/BasePremium
/text()
)[1]
with sql:variable("#R15_premium")')
And something similar for TotalPremium. You can, of course, also replace entire nodes, but that seems unnecessary here.

sql waits for sp/rpc/stmt completed and other events

In SQL XE for sp/rpc/stmt completed events it will be great if we can include wait types like IO/Network waits etc. Just like we can see reads/cpu/duration, If we can also gets other resource waits, we can get a good idea why sql is slow during scenarios where the duration/CPU is high and reads are low.
You can actually track the wait statistics of a query but the other way around - by tracking the wait statistics themselves. Take a look at the following snippet and the result image:
CREATE EVENT SESSION [Wait Statistics] ON SERVER
ADD EVENT sqlos.wait_info
(
ACTION(sqlserver.database_name,sqlserver.session_id,sqlserver.sql_text)
WHERE (
opcode = N'End'
AND duration > 0
)
),
ADD EVENT sqlos.wait_info_external
(
ACTION(sqlserver.database_name,sqlserver.session_id,sqlserver.sql_text)
WHERE (
opcode = N'End'
AND duration > 0
)
)
Here we capture the end of every wait (this is done because at this point SQL Server knows the duration of the statistic, so we can output it int he result) that has has duration greater than 0. In the ACTION part we retrieve the database name, the text of the query that caused the statistic and the session id of the query.
Beware though. Tracking wait statistics through Extended Events(and not through sys.dm_os_wait_stats that collects aggregate data) can generate a ton of data overwhelmingly fast. Should you choose this method, you should define very carefully which wait statistics you want to keep track of and what from what duration on the statistic causes you problem.

SQL bit field filtering

just a quick question here.
Lets say I have a stored procedure for seleting records from a table.
select * from tbl_table
where deleted = #deleted
So for this above, I must pass in a parameter being either TRUE or FALSE.
Is it possible to return results where deleted is equal to TRUE and FALSE but retaining the option to pass in a parameter. So I guess, if no parameter is passed in, there is no filter.
The other way I thought was to do this..
select * from tbl_table
where deleted = #deleted1
and deleted = #deleted2
So you have 2 parameters for the same filter. This way you can do true or false or set both filters the same - giving more leeway.
If anyone has any ideas or thoughts on this that would be great!
set your parameter as nullable (= NULL) and then
select * from tbl_table
where (#deleted IS NULL) OR (deleted = #deleted)
Then do not supply the parameter (or explicitly supply as NULL), when you do not want the filter by that parameter to be applied.
(But be aware this can sometimes have parameter sniffing consequences, especially with a large number of parameters)

Resources