How to detect where SET IMPLICIT_TRANSACTIONS ON? - sql-server

I have a c++ application and run it on
SQL Server 2019
server1\db1 - it works fine
server1\db2 - it works strange
The app works different. I have detected in Profiler that db2 has
set implicit_transactions on
but the db1 has no this set.
I cannot find where this settings is: the app has no this statement.
Where it can be? may be implicitly?

You can check the setting with:
select case when ##Options & 2 = 0 then 'Off' else 'On' end as Implicit_Transactions_State;
Ref: ##Options and user options.

Related

Passing Parameter to SQL from Batch File - Garbage Value Appears

I am trying to pass parameters to SQL script as mentioned here. Here
This is my batch file.
testUpdate.bat
#echo off
sqlplus myuser#mydb/mypassword #updateRundate 25042018
pause
This is my sql file
updateRundate.sql
update SB_ER_RUNDATE set rundate = TO_DATE( '&1', 'ddmmyyyy');
commit;
exit;
I am getting the following error
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
old 1: update SB_ER_RUNDATE set rundate = TO_DATE( '&1', 'ddmmyyyy')
new 1: update SB_ER_RUNDATE set rundate = TO_DATE( 'to', 'ddmmyyyy')
update SB_ER_RUNDATE set rundate = TO_DATE( 'to', 'ddmmyyyy')
*
ERROR at line 1:
ORA-01858: a non-numeric character was found where a numeric was expected
Commit complete.
Instead of the passed parameter, garbage value is appearing in the query. Please help me to resolve this issue.
Update
The path of my sqlplus installation is
C:\app\nt to de softwares\product\11.1.0\client_1
I have observed that, if I am outputting &3 instead of &1, I am getting the value as
softwares\product\11.1.0\client_1\product\11.1.0\client_1\sqlplus\admin\glogin.sql
&1 outputs the value of 'to' . This is in fact part of the installation path.
Update 2
I have tried the second answer in this post. The strange thing is that this script is not working in my system and it prints 'to' at the position of the parameter. But the same is working in another PC which has the same SQL plus installation.

Why does Change Data Capture (SQL Server) job auto stop after specific duration?

I'm currently synchronizing data between Maria <--> MSSQL. That is 2 way sync.
I used SQL Server on Windows and everything works well until several days before... I switched all the test DB to Linux server, so MSSQL was run on a Docker container (the official image).
My Env
MSSQL Docker image
Ubuntu (MacOS also), the CPU and RAM requirement was ensured both for device and Docker.
My problem:
The SQL Agent Job ran perfectly for ~10 minutes. After that, no changes were captured into cdc.dbo_MyTrackedTable_CT.
I want this CDC job will run forever.
I got this message:
Executed as user: 1b23b4b8a3ec\1b23b4b8a3ec$.
Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32). [SQLSTATE 42000] (Error 217)
My inspection
EXEC msdb.dbo.sp_help_job
#job_name = N'cdc.MyDBName_capture',
#job_aspect = N'ALL' ;
Return: last_outcome_message
The job failed. The Job was invoked by User sa. The last step to run
was step 2 (Change Data Capture Collection Agent).
.
Next, take a further inspection:
SELECT
job.*, '|' as "1"
, activity.*, '|' as "2", history.*
, CASE
WHEN history.[run_status] = 0 THEN 'Failed'
WHEN history.[run_status] = 1 THEN 'Succeeded'
WHEN history.[run_status] = 2 THEN 'Retry (step only)'
WHEN history.[run_status] = 3 THEN 'Canceled'
WHEN history.[run_status] = 4 THEN 'In-progress message'
WHEN history.[run_status] = 5 THEN 'Unknown'
ELSE 'N/A' END as Run_Status
FROM msdb.dbo.sysjobs_view job
INNER JOIN msdb.dbo.sysjobactivity activity ON job.job_id = activity.job_id
INNER JOIN msdb.dbo.sysjobhistory history ON job.job_id = history.job_id
WHERE 1=1
AND job.name = 'cdc.MyDBName_capture'
AND history.run_date = '20180122'
Return:
See this SQL result Image
Sorry I don't have enough repu to embed img, so the link instead.
As you can see the CDC job will start and run..and..retry for 10 times, after 10times, I cannot capture changes anymore.
I need to start the job again by:
EXEC msdb.dbo.sp_start_job N'cdc.MyDbName_capture';
Then foreach ~1 minutes, the job retry --> till 10 --> job was stopped ¯_(ツ)_/¯
So can you tell me why and how to fix it ??
FYI, This is my job configuration:
-- https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sys-sp-cdc-add-job-transact-sql
EXECUTE sys.sp_cdc_change_job
#job_type = N'capture',
#maxscans = 1,
#maxtrans = 500,
#continuous = true,
#pollinginterval = 1
;
It's also not a trigger issue right? I feel dangerous when trying to turn trigger off, but no luck was made.
-- Turn off recursion trigger
ALTER DATABASE MyDBName
SET RECURSIVE_TRIGGERS OFF;
I am experiencing the same thing on SQL server 2017 running under windows server. Interestingly the same system has been running for no problems for years under SQL2012 so I am thinking it may be some bug introduced along the way.
I found with some retries the problem cleared so as a workaround I edited the job and increased the number of retries and haven't seen it again yet.
See KB4073684 - FIX: Change data capture does not work in SQL Server 2017.
This happens due to a declared bug:
Microsoft has confirmed that this is a problem in the Microsoft products...
Fix is included in Cumulative Update 4 for SQL Server 2017. However, they recommend simply installing the latest cumulative version:
Each new build for SQL Server 2017 contains all the hotfixes and security fixes that were in the previous build. We recommend that you install the latest build for SQL Server 2017.

How to tell if a SQL Database has QUERY_STORE enabled?

How can I tell if a Azure SQL Database has QUERY_STORE turned on?
You enable it with this command:
ALTER DATABASE <database_name> SET QUERY_STORE = ON;
I figure it should be simple to check the database for this, but I have not found the trick.
FYI, I tried this command on a database that had it enabled, but the command just returned null:
SELECT DATABASEPROPERTYEX ('<database_name>', 'QUERY_STORE')
This DMV sys.database_query_store_options should allow you to determine if QUERY_STORE is enabled:
SELECT desired_state_desc ,
actual_state_desc ,
readonly_reason,
current_storage_size_mb ,
max_storage_size_mb ,
max_plans_per_query
FROM sys.database_query_store_options ;
Description of Actual_state_Desc states :
OFF (0)
-Not Enabled
READ_ONLY (1)
Query Store may operate in read-only mode even if read-write was specified by the user. For example, that might happen if the database is in read-only mode or if Query Store size exceeded the quota
READ_WRITE (2)
Query store is on and it is capturing all queries
ERROR (3)
Extremely rarely, Query Store can end up in ERROR state because of internal errors. In case of memory corruption, Query Store can be recovered by requesting READ_WRITE mode explicitly, using the ALTER DATABASE SET QUERY_STORE statement. In case of corruption on the disk, data must be cleared before READ_WRITE mode is requested explicitly.
David's answer shows if the Query store is enabled for the current database - so you would need to loop through them.
This query shows if the Query store is enabled for all databases (but doesn't show any details).
SELECT
d.name,
d.is_query_store_on
FROM sys.databases AS d

Detect Sql Express From TSQL

I need a safe (i.e consistent, robust) way of detecting whether or not the sql server I'm accessing is Sql Express. I think I'd prefer to be able to do this from TSQL, since I already have a connection string and all the libraries I need to execute TSQL (this should help avoid issues with whether or not WMI is installed/running, the user has permissions to access the registry etc).
Does anyone know of a way to do this ?
Thanks.
PS: Basically I want to do this so I can monitor my database size against the 4gb limit and take action when I approach it... but if I'm running on a full Sql Server edition then I don't want the code to worry about it since there is no (practical) hard coded limit. I could put in a manual setting in my program, but it would be much nicer if the code just did the right thing automatically, hence the need to know if the server is the 'Express' edition or not.
Use
SELECT SERVERPROPERTY('EditionID')
or
SELECT SERVERPROPERTY('Edition')
to detect which version of SQLServer is running.
http://msdn.microsoft.com/en-us/library/ms174396.aspx
This will return 0 if it's not, and something non-zero (126 here) if it is:
select charindex('Express Edition',##version)
Example in a boolean context:
if (select charindex('Express Edition',##version)) > 0
begin
print 'Express edition!'
end
else
begin
print 'Not Express edition!'
end
The SERVERPROPERTY function was already mentioned in multiple other answers, but there's a better solution than checking if a string contains "Express Edition": the EngineEdition argument, which returns an int value.
Quote from the link:
EngineEdition
Database Engine edition of the instance of SQL Server installed on the
server.
1 = Personal or Desktop Engine (Not available in SQL Server 2005 and
later versions.)
2 = Standard (This is returned for Standard, Web, and Business
Intelligence.)
3 = Enterprise (This is returned for Evaluation, Developer, and both
Enterprise editions.)
4 = Express (This is returned for Express, Express with Tools and
Express with Advanced Services)
5 = SQL Database
6 - SQL Data Warehouse
Base data type: int
So you can check for Express Edition like this:
if SERVERPROPERTY('EngineEdition') = 4
begin
select 'Express'
end
else
begin
select 'not Express'
end
There are a number of ways:
EXEC sp_server_info 2
Or
SELECT ##version
Or
SELECT serverproperty('ProductVersion')
You Can Also do this:
DECLARE #ver nvarchar(128)
SET #ver = CAST(serverproperty('ProductVersion') AS nvarchar)
SET #ver = SUBSTRING(#ver, 1, CHARINDEX('.', #ver) - 1)
IF ( #ver = '8' )
SELECT 'SQL Server 2000'
ELSE IF ( #ver = '9' )
SELECT 'SQL Server 2005'
ELSE
SELECT 'Unsupported SQL Server Version'
More info at: http://blog.devstone.com/aaron/default,date,2006-12-15.aspx
You can use SERVERPROPERTY('Edition') which will return "Express Edition"
What happens in SQL Server Express if you don't monitor the size, but get to the limit? Are there warnings first? Events in the event log?
If so, then you might do better to allow SQL Server to issue the warnings, and then just listen to them. The same might well apply for a SQL Server Enterprise installation if a disk gets full.

Version Agnostic SQL Server Script/Statement that detects existence of a specific database

Due to the packaged nature of the release, a SQL Server script (well more of a statement) needs to be created that can execute correctly on SQL Server 7.0 thru 2008 which can essentially achieve this:
if exists(select * from sys.databases where name = 'Blah')
Reasons this is difficult:
SQL 7 'sys.databases' is not valid
SQL 2008 'sysdatabases' is not valid
I stupidly parsed out the version number using serverproperty, to allow an IF depending on the version:
if (select CONVERT(int,replace(CONVERT(char(3),serverproperty ('productversion')),'.',''))) >= 80
Then discovered serverproperty does not exist under SQL 7.
Note that the SQL can be remote from the install, so no futzing around on the local machine - reg entries/file versions etc is of any use.
SQL Server error handling (especially 7.0) is poor, or maybe I don't understand it well enough to make it do a kind of try/catch.
I am now getting problem blindness to this, so any pointers would be appreciated.
Thanks,
Gareth
Try
USE database
and test ##ERROR.
USE database
IF ##ERROR <> 0 GOTO ErrExit
logic ...
RETURN 0
ErrExit:
RETURN 1
(or RAISERROR, or ...)
Thanks G Mastros
This looks like it might yield a 100% solution. It is available under SQL 7.
I need to complete and test, but at first glance I think it will fly.
Here's the draft code FYI.
create table #dwch_temp
(
name sysname
,db_size nvarchar(13)
,owner sysname
,dbid smallint
,created nvarchar(11)
,status nvarchar(600)
,compatibility_level tinyint
)
go
insert into #dwch_temp
exec sp_helpdb
if exists(select name from #dwch_temp where name = 'DWCHServer')
-- run the code
drop table #dwch_temp
You could try a TRY... CATCH around a USE [DatabaseName].
I don't have access to a SQL 7 instance, but I encourage you to try:
sp_helpDB
I know this works on sql 2000 and sql 2005 to get a list of databases. I suspect it works on SQL 7, too.
sysdatabases is a remnant from the Sybase era and is still present in SQL 2008 (although deprecated). You can check for the existence of a database with a query like this:
IF EXISTS (SELECT 1 FROM master..sysdatabases where name = 'Blah')

Resources