Distributed Transaction SQL Error using Linked Server - sql

I'm having some database troubles, and can't seem to find a solution anywhere for this specific problem. I'm trying to grab information from a database using a table on the database and comparing it to a table on a linked server
[3/7/14 10:10:14:181 EST] 00000021 SystemErr R org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: The operation could not be performed because OLE DB provider "SQLNCLI" for linked server "EADWH02" was unable to begin a distributed transaction.
### The error may involve com.moog.app.weldlog.dao.mybatis.WeldLogMapping.listEmployee-Inline
### The error occurred while setting parameters
### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: The operation could not be performed because OLE DB provider "SQLNCLI" for linked server "EADWH02" was unable to begin a distributed transaction.
Here is one of the specific stored procedures that is throwing this error:
#workOrder varchar(25) = null,
#idPartNumber varchar(25) = null
begin
IF #workOrder is null
SELECT DISTINCT TOP 25 WO.WO_NBR, PARTS.PART_NBR
FROM EADWH02.MEDW.LBR.WO WO
JOIN EADWH02.MEDW.MFG.PARTS PARTS
ON PARTS.PART_KEY = WO.PART_KEY
AND PARTS.SRC_DB_KEY = WO.SRC_DB_KEY
WHERE (WO.WO_TYPE_KEY = '2' or WO.WO_TYPE_KEY = '3' or WO.WO_TYPE_KEY = '4' or WO.WO_TYPE_KEY = '5') and
(PARTS.PART_NBR like '' + #idPartNumber + '%')
ELSE IF #idPartNumber is null
SELECT DISTINCT TOP 25 WO.WO_NBR, PARTS.PART_NBR, dbo.getDescriptions(WO.WO_NBR) as strDescriptions
FROM EADWH02.MEDW.LBR.WO WO
JOIN EADWH02.MEDW.MFG.PARTS PARTS
ON PARTS.PART_KEY = WO.PART_KEY
AND PARTS.SRC_DB_KEY = WO.SRC_DB_KEY
WHERE ((WO.WO_TYPE_KEY = '2' or WO.WO_TYPE_KEY = '3' or WO.WO_TYPE_KEY = '4' or WO.WO_TYPE_KEY = '5') and
(WO.WO_NBR like '' + #workOrder))
ORDER BY WO.WO_NBR
end
((dbo.getDescriptions is a scalar-valued function and works fine))
And here is my xml mapping file in the project:
<select id="listWorkOrder" statementType="CALLABLE" parameterType="WorkOrder" resultMap="WorkOrderMap"> {
call listWorkOrder( #{workOrder, jdbcType=VARCHAR},
#{partNumber, jdbcType=VARCHAR})
}
</select>
Any chance anyone knows what's causing this error? This sql stored procedure breaks both on a remote server we're using and on a local server. Thanks for the assistance!

Related

Excel "The multi-part identifier could not be bound" When Using Parameters

I have a SQL query in Excel that will work just fine if I hard code the dates into the query. As soon as I try to change them to ?'s it gives the error. I've used parameterized queries like this in loads of reports, so I'm not sure why this one is suddenly not working.
The full error is [Microsoft][ODBC SQL Server Driver][SQL Server]The multi-part identifier "cancel.arrival_date" could not be bound. which pops up twice.
Here is my query with the ? in it that gives the error:
SELECT cancel.reservation_number, (client.last_name + ', ' + client.first_name) AS 'guest_name',
cancel.cancel_date_time, cancel.arrival_date,
DATEDIFF(DAY, cancel.cancel_date_time, cancel.arrival_date) AS 'Days Out', cancel.cancel_reason,
CASE
WHEN EXISTS (SELECT *
FROM gbfol_head head
LEFT JOIN gbfol_det det ON head.folio_number = det.folio_number
WHERE cancel.reservation_number = head.source_id
AND head.folio_type <> 'b' AND det.posting_code = 'admn') THEN
'ADMN Charged'
ELSE
'No ADMN Fee'
END AS 'ADMN',
cancel.amount, cancel.cancel_clerk_code, cancel.sba_text
FROM canceled cancel
LEFT JOIN reservation res ON cancel.reservation_number = res.reservation_number
LEFT JOIN clients client ON res.home_client_code = client.client_code
WHERE DATEDIFF(DAY, cancel.cancel_date_time, cancel.arrival_date) < 21
AND (cancel.arrival_date BETWEEN ? AND ?)
If I change the last line to AND (cancel.arrival_date BETWEEN '2019-12-01' AND '2019-12-10') it works fine.
I have also tried using AND (cancel.arrival_date >= ? AND cancel.arrival_date <= ?) which didn't work either, same error.

No more data to read from socket after execute this sql

Why when I execute this SQL using SQL Developer it said
No more data to read from socket
but when I reconnect the connection then remove fetch next 5 rows only it executes perfectly?
It also happens when I execute this query on web application, it gives this error:
oci_execute(): ORA-03113: end-of-file on communication channel
Process ID: 4136
Session ID: 18
Serial number: 36957
SELECT PO_ID,
ENQ_ID,
TITLE,
SYS_BRKDWN_ID,
TECH_HAND_USR_ID,
PROJ_NO,
SUPPL_NO,
approver_usr_id,
VER
FROM S181
WHERE approver_usr_id ='EETEC'
and reject_date is null
AND po_hdr_biz.can_approve(po_id, enq_id, ver,'EETEC') = 1
AND EXISTS (
SELECT NULL
FROM po_approvals
WHERE po_approvals.po_id = s181.po_id
AND po_approvals.ver = s181.ver
AND po_approvals.init = 'EETEC'
AND po_approvals.init = s181.approver_usr_id
AND po_approvals.po_id IS NOT NULL
AND po_approvals.approve_date IS NULL
UNION
SELECT NULL
FROM po_approvals
WHERE po_approvals.enq_id = s181.enq_id
AND po_approvals.ver = s181.ver
AND po_approvals.init = 'EETEC'
AND po_approvals.init = s181.approver_usr_id
AND po_approvals.enq_id IS NOT NULL
FETCH NEXT 5 ROWS ONLY
);

Error "DBCC execution completed" when running data connection from Excel

I get this error when I try to run this data connection from Excel 2010
Connection string:
Provider=SQLOLEDB.1;Persist Security Info=True;User ID=sa;Data Source=sql-
server;Use Procedure for Prepare=1;Auto Translate=True;Packet
Size=4096;Workstation ID=PV-SAMSUNG;Use Encryption for Data=False;Tag with
column collation when possible=False;Initial Catalog=BVR_AUTOMAX
Command text:
EXECUTE sp_executesql N'
BEGIN
DBCC TRACEON(8765);
SELECT *
FROM OPENQUERY(SugarCRM, ''
select ticker_symbol,count(a.id) as pocet,sum(case when ifnull(a.account_erp_id,0)=''''0'''' then 0 else 1 end) as bvr, count(a.id) - sum(case when ifnull(a.account_erp_id,0)=''''0'''' then 0 else 1 end) as delta
from crm.accounts a inner join crm.users u on a.assigned_user_id=u.id
inner join crm.accounts_cstm ac on a.id=ac.id_c
where a.deleted=0
group by ticker_symbol
having delta>0 and bvr>0
order by delta desc;
'' );
END';
When I run this code in MS SQL Server Mngt Studio it works fine.
Thanks for your help
Petr
I found a solution, quite simple one. Just change this line of code to the following (add the WITH NO_INFOMSGS argument)
DBCC TRACEON(8765) WITH NO_INFOMSGS ;

How to get current instance name from T-SQL

How can I get the SQL Server server and instance name of the current connection, using a T-SQL script?
Just found the answer, in this SO question (literally, inside the question, not any answer):
SELECT ##servername
returns servername\instance as far as this is not the default instance
SELECT ##servicename
returns instance name, even if this is the default (MSSQLSERVER)
How about this:
EXECUTE xp_regread #rootkey='HKEY_LOCAL_MACHINE',
#key='SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQl',
#value_name='MSSQLSERVER'
This will get the instance name as well. null means default instance:
SELECT SERVERPROPERTY ('InstanceName')
http://technet.microsoft.com/en-us/library/ms174396.aspx
SELECT ##servername will give you data as server/instanceName
To get only the instanceName you should run select ##ServiceName query .
Why stop at just the instance name? You can inventory your SQL Server environment with following:
SELECT
SERVERPROPERTY('ServerName') AS ServerName,
SERVERPROPERTY('MachineName') AS MachineName,
CASE
WHEN SERVERPROPERTY('InstanceName') IS NULL THEN ''
ELSE SERVERPROPERTY('InstanceName')
END AS InstanceName,
'' as Port, --need to update to strip from Servername. Note: Assumes Registered Server is named with Port
SUBSTRING ( (SELECT ##VERSION),1, CHARINDEX('-',(SELECT ##VERSION))-1 ) as ProductName,
SERVERPROPERTY('ProductVersion') AS ProductVersion,
SERVERPROPERTY('ProductLevel') AS ProductLevel,
SERVERPROPERTY('ProductMajorVersion') AS ProductMajorVersion,
SERVERPROPERTY('ProductMinorVersion') AS ProductMinorVersion,
SERVERPROPERTY('ProductBuild') AS ProductBuild,
SERVERPROPERTY('Edition') AS Edition,
CASE SERVERPROPERTY('EngineEdition')
WHEN 1 THEN 'PERSONAL'
WHEN 2 THEN 'STANDARD'
WHEN 3 THEN 'ENTERPRISE'
WHEN 4 THEN 'EXPRESS'
WHEN 5 THEN 'SQL DATABASE'
WHEN 6 THEN 'SQL DATAWAREHOUSE'
END AS EngineEdition,
CASE SERVERPROPERTY('IsHadrEnabled')
WHEN 0 THEN 'The Always On Availability Groups feature is disabled'
WHEN 1 THEN 'The Always On Availability Groups feature is enabled'
ELSE 'Not applicable'
END AS HadrEnabled,
CASE SERVERPROPERTY('HadrManagerStatus')
WHEN 0 THEN 'Not started, pending communication'
WHEN 1 THEN 'Started and running'
WHEN 2 THEN 'Not started and failed'
ELSE 'Not applicable'
END AS HadrManagerStatus,
CASE SERVERPROPERTY('IsSingleUser') WHEN 0 THEN 'No' ELSE 'Yes' END AS InSingleUserMode,
CASE SERVERPROPERTY('IsClustered')
WHEN 1 THEN 'Clustered'
WHEN 0 THEN 'Not Clustered'
ELSE 'Not applicable'
END AS IsClustered,
'' as ServerEnvironment,
'' as ServerStatus,
'' as Comments
I found this:
EXECUTE xp_regread
#rootkey = 'HKEY_LOCAL_MACHINE',
#key = 'SOFTWARE\Microsoft\Microsoft SQL Server',
#value_name = 'InstalledInstances'
That will give you list of all instances installed in your server.
The ServerName property of the SERVERPROPERTY function and ##SERVERNAME return similar information. The ServerName property provides the Windows server and instance name that together make up the unique server instance. ##SERVERNAME provides the currently configured local server name.
And Microsoft example for current server is:
SELECT CONVERT(sysname, SERVERPROPERTY('servername'));
This scenario is useful when there are multiple instances of SQL Server installed on a Windows server, and the client must open another connection to the same instance used by the current connection.
To get the list of server and instance that you're connected to:
select * from Sys.Servers
To get the list of databases that connected server has:
SELECT * from sys.databases;
Just to add some clarification to the registry queries. They only list the instances of the matching bitness (32 or 64) for the current instance.
The actual registry key for 32-bit SQL instances on a 64-bit OS is:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server
You can query this on a 64-bit instance to get all 32-bit instances as well. The 32-bit instance seems restricted to the Wow6432Node so cannot read the 64-bit registry tree.
You can get your server name, machine name and instance name with Transact-SQL(T-SQL) as shown below:
SELECT ##SERVERNAME -- DESKTOP-OVPADTC\SQLEXPRESS
SELECT SERVERPROPERTY ('ServerName') -- DESKTOP-OVPADTC\SQLEXPRESS
SELECT HOST_NAME() -- DESKTOP-OVPADTC
SELECT SERVERPROPERTY ('MachineName') -- DESKTOP-OVPADTC
SELECT ##SERVICENAME -- SQLEXPRESS
SELECT SERVERPROPERTY ('InstanceName') -- SQLEXPRESS
another method to find Instance name- Right clck on Database name and select Properties, in this part you can see view connection properties in left down corner, click that then you can see the Instance name.

SQL Job Failing but not the stored procedure

EDIT 4/18:
I want to thank everyone who has answered so far. As a test I have set up a new job which has just one step in it,
EXECUTE p_CallLog_GetAbandonedCallsForCallList
This procedure itself runs just fine and reports no errors or warnings but will not run when executed as part of a job. The error I receive when running the job is:
Executed as user: NT AUTHORITY\SYSTEM. OLE DB provider 'SQLOLEDB' reported an error. [SQLSTATE 42000] (Error 7399) [SQLSTATE 01000] (Error 7312) OLE DB error trace
[OLE/DB Provider 'SQLOLEDB' IDBInitialize::Initialize returned 0x80004005: ].
[SQLSTATE 01000] (Error 7300). The step failed.
I have tried changing the run as user selection and every other selection I try results in an error of:
Executed as user: Db2WebCal. Remote access not allowed for Windows NT user activated
by SETUSER. [SQLSTATE 42000] (Error 7410). The step failed.
All of the users I have tried do have a local login setup on the linked server.
The p_CallLog_GetAbandonedCallsForCallList procedure is as follows:
CREATE PROCEDURE [dbo].[p_CallLog_GetAbandonedCallsForCallList]
AS
BEGIN
DECLARE #SrvrName varchar(255)
DECLARE #HoursOld int --only get abandoned call that are fresher than #HoursOld
SET #HoursOld = 2 /*was normal default */
SET #SrvrName = CAST(ServerProperty('MachineName') as varchar(255))
CREATE TABLE #tmpAbandonedCalls
(
[ID] INT NULL,
StartTime DateTime NULL,
CallerIDNumber varchar(255) NULL,
CallerIDCount INT NULL,
Holdtime INT NULL,
DIDNumber varchar(20) NULL,
CustomData varchar(255) NULL,
FromFirstName varchar(100) NULL,
FromLastName varchar(100) NULL,
CallType int NULL
)
IF #SrvrName <> 'ROME' BEGIN
INSERT INTO #tmpAbandonedCalls
SELECT
cl.[ID],
cl.StartTime,
cl.CallerIDNumber,
LastAbandonedCallID.cnt as CallerIDCount,
cl.HoldTime,
right(cl.DIDNumber,10) as DIDNumber,
REPLACE(right(left(cl.CustomData,charindex(';',cl.CustomData) - 1), len(left(cl.CustomData,charindex(';',cl.CustomData) - 1)) - charindex('=',cl.CustomData)) , ' NAME','') as CustomData,
cl.FromFirstName,
cl.FromLastName,
2 AS CallType -- T_L_CallType obctAbandoned
FROM
[StrataCS.Perceptionist.local].TVDB.dbo.CallLog CL LEFT OUTER JOIN
/*=============================================
This derived table lists the CallerID's and the most
recent Call Log ID for candidate calls
=============================================*/
(
SELECT
CallerIDNumber, Max(ID) as ID, count(*) as cnt
FROM
[StrataCS.Perceptionist.local].TVDB.dbo.CallLog CL
WHERE
--Last n days
--StartTime >= DATEADD(dd,-#DaysBack,CAST(CONVERT(VARCHAR(10),GETDATE(),112) as DATETIME))
--Get calls only from within the last two hours.
StartTime >= DATEADD(hh,-2,GETDATE())
AND
LEFT(CustomData,11) = 'CompanyName'
AND
CHARINDEX('Db2ID', CustomData) > 0
AND
CallerIDNumber <> ''
AND
Len(CallerIDNumber) = 10
AND
(cl.HoldTime > 0) --0 holdtime is generally an automated call that we will not want to call again
GROUP BY
CallerIDNumber
) as LastAbandonedCallID
ON
CL.CallerIDNumber = LastAbandonedCallID.CallerIDNumber
WHERE
--Last n days
--StartTime >= DATEADD(dd,-#DaysBack,CAST(CONVERT(VARCHAR(10),GETDATE(),112) as DATETIME))
--Get calls only from within the last two hours.
cl.StartTime >= DATEADD(hh,(-1 * #HoursOld),GETDATE())
AND
--determine abandoned calls
CASE
WHEN CL.Result IN (0, 3, 11) THEN 0
WHEN CL.Result IN (1, 2) THEN 1
WHEN CL.Result IN (4, 9) THEN 2
WHEN CL.Result = 5 THEN 3
WHEN CL.Result = 6 THEN 4
WHEN CL.Result = 8 THEN 5
WHEN CL.Result = 10 THEN 6
WHEN CL.Result = 12 THEN 7
WHEN CL.Result = 13 THEN 8
WHEN CL.Result = 14 THEN 9
ELSE -CL.Result
END = 0
--Calls which have hit the call queue will have both a CompanyName and Db2ID in custom data.
AND
LEFT(CustomData,11) = 'CompanyName'
AND
CHARINDEX('Db2ID', CustomData) > 0
AND
--omit calls with no caller id -- or from IGC 6143847400
(
CL.CallerIDNumber <> ''
--OR CL.CallerIDNumber = '6143847400'
)
AND
--make sure the caller id has 10 digits
Len(CL.CallerIDNumber) = 10
AND
--The abandoned call must be the most recent call from this caller id
--CL.ID >= isnull(LastAbandonedCallID.ID,-#DaysBack)
CL.ID >= isnull(LastAbandonedCallID.ID,-1)
AND
(CL.HoldTime > 0) --0 holdtime is generally an automated call that we will not want to call again
ORDER BY
--sort by call time, most recent first.
StartTime DESC
-- Company has opted out of the Abandoned Callback program
DELETE #tmpAbandonedCalls
FROM
#tmpAbandonedCalls tmp
INNER JOIN dbo.T_CompanyPhoneSetup cps
on tmp.DIDNumber = cps.DID
INNER JOIN T_CompanyAbandonedCallbackOptOut aco
ON cps.CompanyID = aco.CompanyID
AND
aco.OptOutIsActive = 1
--Delete calls that have had a terminating outcome or have been returned within the last 20 minutes
DELETE #tmpAbandonedCalls
FROM
#tmpAbandonedCalls
INNER JOIN
(
SELECT
c.CallLogID
FROM
T_Call c (nolock)
INNER JOIN #tmpAbandonedCalls tmp
on tmp.ID = c.CallLogID
LEFT OUTER JOIN T_L_Need n
ON c.NeedID = n.NeedID
LEFT OUTER JOIN T_L_Outcome o
ON c.OutcomeID = o.OutcomeID
LEFT OUTER JOIN dbo.T_L_CallCampaignDetailStatus ccds
ON o.CCDetailStatusID = ccds.CCDetailStatusID
LEFT OUTER JOIN dbo.T_Company co
ON c.CompanyID = co.CompanyID
LEFT OUTER JOIN dbo.T_L_ProductLine pl
ON co.ProductLineID = pl.ProductLineID
LEFT OUTER JOIN T_CompanyAbandonedCallbackOptOut aco
ON (c.CompanyID = aco.CompanyID) and (aco.OptOutIsActive = 1)
GROUP BY
c.CallLogID
HAVING
--Calls that have an outcome that include at least one terminating outcome
(SUM(CAST(isnull(ccds.IsTerminal,0) as INT)) > 0)
OR
(
--Calls that have been returned less than 20 minutes ago
(SUM(CAST(isnull(ccds.IsTerminal,0) as INT)) = 0)
AND
GETDATE() <= DATEADD(mi,20,Max(c.EnteredOn))
)
OR
(
--Calls for Perceptionist Lite product line
(MAX(co.ProductLineID) = 2) -- Perceptionist Lite
)
) LastCall
ON
#tmpAbandonedCalls.[ID] = LastCall.CallLogID
END
INSERT INTO T_OutboundCallList
(TrackingID, Company, CompanyDID, Phone, CallType)
SELECT
#tmpAbandonedCalls.[ID],
#tmpAbandonedCalls.CustomData,
#tmpAbandonedCalls.DIDNumber,
#tmpAbandonedCalls.CallerIDNumber,
#tmpAbandonedCalls.CallType
FROM
#tmpAbandonedCalls
ORDER BY
StartTime
END
GO
ORIGINAL:
I have the following stored procedure that is used to fill a table with values.
PROCEDURE [dbo].[p_OutboundCallList_Create]
AS
BEGIN
TRUNCATE TABLE T_OutboundCallList
EXECUTE p_LeadVendor_GetCallsForCallList
EXECUTE p_CallCampaign_GetCallsForCallList
EXECUTE p_CallLog_GetAbandonedCallsForCallList
EXECUTE p_NoSaleFollowUp_GetCallsForCallList
END
Running this works fine and the table is filled. After creating a job and adding the following step:
EXEC p_OutboundCallList_Create
The job fails with the following error message:
Executed as user: NT AUTHORITY\SYSTEM. Warning: Null value is eliminated
by an aggregate or other SET operation. [SQLSTATE 01003] (Message 8153)
Warning: Null value is eliminated by an aggregate or other SET operation.
[SQLSTATE 01003] (Message 8153) OLE DB provider 'SQLOLEDB' reported an error.
[SQLSTATE 42000] (Error 7399) [SQLSTATE 01000] (Error 7312) OLE DB error trace
[OLE/DB Provider 'SQLOLEDB' IDBInitialize::Initialize returned 0x80004005: ].
[SQLSTATE 01000] (Error 7300). The step failed.
If I comment out the line
EXECUTE p_CallLog_GetAbandonedCallsForCallList
..the job runs fine. This stored procedure (p_CallLog_GetAbandonedCallsForCallList) does rely on a linked server and runs fine by itself and also runs fine when I run p_OutboundCallList_Create. It only fails when I run it as part of a job. I have tried running as a different user (sa, benderle, etc.) and always get the same result (failed).
"Null value is eliminated by an aggregate or other SET operation" is a SQL Server warning, which means you won't see it in the output if you run your query and this warning is raised (switch to the "Messages" tab in SQL Server Management Studio to see this).
Although it's a warning, presumably any warnings in a SQL job cause the job to error out. Fix the p_CallLog_GetAbandonedCallsForCallList procedure so it doesn't raise that warning and you job will work as expected.
I woulf be interested in seeing the code in p_CallLog_GetAbandonedCallsForCallList, as it may explain more as to why this is happening for the user NT AUTHORITY\SYSTEM.
The message occurs when you perform an aggregation (e.g. sum(), max(), count() on a data set that has a null in it).
To fix this, you may need to put an ISNULL() around the field in question, or use an INNER JOIN instead of a LEFT or RIGHT JOIN.
To disable warning that throw error in Sql Server Agent tasks.
The tasks that are launched from the SQL SERVER AGENT (scheduled), give an error, if there is a warning of the style:
"Null value is eliminated by an aggregate or other SET operation"
This message can be disabled by SET ANSI_WARNING OFF
But in some cases, there are sql statements that require this value to be on to avoid errors like:
Heterogeneous queries require the ANSI_NULLS and ANSI_WARNINGS options to be set for the connection. This ensures consistent query semantics. Enable these options and then reissue your query
Therefore, there is no other solution than to prevent SQL SERVER AGENT from considering it an error.
This can be achieved by modifying the values ​​in the REGISTRY (REGEDIT)
Modify the entries, depending on your version of SQL SERVER:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.MSSQLSERVER\SQLServerAgent
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.SQL2012\SQLServerAgent
Add as 'no error' the message id you want to disable: 7405