我在 SQL Server 2016 中有一个存储过程,我在其中执行外部 R 脚本。我无法弄清楚为什么该程序对我有用,但是每当有人运行它时,他们都会收到此错误。他们运行一次后,我也无法运行该程序,并且此错误是默认结果:
Location: tmpilb.cpp:2532
Expression: fFalse
SPID: 76
Process ID: 2036
Description: Attempt to access expired blob handle (1)
Msg 21, Level 20, State 1, Line 0
Warning: Fatal error 3624 occurred at Jun 19 2017 3:07PM. Note the error
and time, and contact your system administrator.
Msg 596, Level 21, State 1, Line 0
Cannot continue the execution because the session is in the kill state.
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command. The results, if any, should
be discarded.
存储过程执行通过 RODBC 链接到单独数据库的 R 脚本、提取数据、执行操作并将结果发送回 SQL 以填充表。
编辑:包括存储过程代码:
USE [Park_Analytics]
GO
/****** Object: StoredProcedure [dbo].[storedproc] Script Date: 6/19/2017 2:40:38 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[storedproc]
@startdate date NULL
AS
set @startdate = ISNULL(@startdate,DATEADD(wk,DATEDIFF(wk,7,GETDATE()),-15))
declare @enddate datetime = dateadd(D,1,@startdate)
create table #temp_results
(Park NVARCHAR(max) NOT NULL,
Turbine int NOT NULL,
avg_wtgp_kw float NULL,
avg_metwndspd_ms float NULL,
avg_metextmp_degc float NULL,
st_wtgp_kw float NULL,
st_metwndspd_ms float NULL,
st_metextmp_degc float NULL,
site_avg_wtgp_kw float NULL,
site_avg_metwndspd_ms float NULL,
site_avg_metextmp_degc float NULL,
site_st_wtgp_kw float NULL,
site_st_metwndspd_ms float NULL,
site_st_metextmp_degc float NULL,
Z_Score_avg_wtgp_kw float NULL,
Z_Score_avg_metwndspd_ms float NULL,
Z_Score_avg_metextmp_degc float NULL,
Alarm_Level_Z_Score_avg_wtgp_kw float NULL,
Alarm_Level_Z_Score_avg_metwndspd_ms float NULL,
Alarm_Level_Z_Score_avg_metextmp_degc float NULL)
insert into #temp_results
EXEC sp_execute_external_script
@language = N'R'
,@script = N'
library(RODBC)
# String to connect to global database
piglobal_str <- ''driver={SQL Server};server=Server.corp.org\\Servername;database=Assets;uid=generic_login;pwd=generic_pwd''
# Connect to the database
Assets <- odbcDriverConnect(piglobal_str)
# Write SQL Query to execute within R
QueryString <- ''SELECT
w.wpp_name as wpp,
pd.wt,
pd.datetime,
pd.datetime_local,
avg_wtgp_kw,
avg_metwndspd_ms,
avg_metextmp_degc,
FROM [Assets].[dbo].[PI_Main10mindata] pd
left join [Assets].[dbo].PI_Main10mindata_temp pt on pt.wpp=pd.wpp and pt.datetime = pd.datetime and pt.wt=pd.wt
left join [Assets].[dbo].[pi_wpps] w on w.wpp_pi = pd.wpp
where pt.datetime between DATEADD(wk,DATEDIFF(wk,7,GETDATE()),-15)
and DATEADD(wk,DATEDIFF(wk,7,GETDATE()),-14)
order by pt.datetime''
# Set query results to a dataframe. as.is parameter is to keep all datatypes exactly the same as they are read.
pidata <- sqlQuery(Assets, QueryString,as.is=TRUE)
# Closing the RODBC Channel
odbcClose(Assets)
# Basic data processing. Setting the datatype to numeric.
pidata[,-which(names(pidata) %in% c("datetime","datetime_local","wpp"))] <-
sapply(pidata[,-which(names(pidata) %in% c("datetime","datetime_local","wpp"))], function(x) as.numeric(x))
# Filter on availability and on kW output
filtered <- pidata[pidata$avg_wtgst_int %in% c(100, 200) & pidata$avg_wtgp_kw > 500 & !(is.na(pidata$avg_wtgp_kw)),]
# Remove date columns and state int column. They wont be important from here on out until theyre put back into the SQL table.
df_turbinefilter <- filtered[,-which(names(filtered) %in% c("datetime","datetime_local","avg_wtgst_int"))]
# Taking out the "avg_" in front of all of the columns. Will make sense later when I rename columns after aggregations.
colnames(df_turbinefilter) <- gsub("avg_","",colnames(df_turbinefilter),perl = TRUE)
## PERFORM AGGREGATIONS ##
library(reshape2)
df_melt <- melt(df_turbinefilter, id= c("wpp","wt"))
agged <- dcast(df_melt, wpp + wt ~ variable, mean)
df_meltst <- melt(df_turbinefilter, id=c("wpp","wt"))
aggedst <- dcast(df_meltst, wpp + wt ~ variable, sd)
# Aggregated data joining
# list of data.frames
list_of_df <- list(agged, aggedst)
# names of data.frames
names(list_of_df) <- c("avg", "st")
# my sequence and names of data.frames in a list
my_seq <- seq_along(list_of_df)
my_list_names <- names(list_of_df)
# Renaming new columns. Including avg_ and st_ for average and standard deviation.
for (i in my_seq) {
names(list_of_df[[my_seq[i]]]) <-
paste(my_list_names[i], names(list_of_df[[my_seq[i]]]), sep = "_")
}
# Binding the columns from the agged table (to keep the nomenclature) with the other aggregate calcs
scored_data <- cbind(agged[,which(names(agged) %in% c("wpp","wt"))],
list_of_df$avg[,-which(names(list_of_df$avg) %in% c("avg_wpp","avg_wt"))],
list_of_df$st[,-which(names(list_of_df$st) %in% c("st_wpp","st_wt"))] )
## SITE AGGREGATIONS ##
df_sitefilter <- df_turbinefilter[,-which(names(df_turbinefilter) %in% c("wt"))]
df_meltsite <- melt(df_sitefilter, id="wpp")
aggedsite <- dcast(df_meltsite, wpp ~ variable, mean)
df_meltstsite <- melt(df_sitefilter, id="wpp")
aggedstsite <- dcast(df_meltstsite, wpp ~ variable, sd)
# Bug - have to create a separate vector
wpp <- aggedsite$wpp
# Aggegrated data joining
# list of data.frames
list_of_dfs <- list(aggedsite, aggedstsite)
# names of data.frames
names(list_of_dfs) <- c("site_avg", "site_st")
# my sequence and names of data.frames in a list
my_seqs <- seq_along(list_of_dfs)
my_list_namess <- names(list_of_dfs)
# Renaming new columns.
for (i in my_seqs) {
names(list_of_dfs[[my_seqs[i]]]) <-
paste(my_list_namess[i], names(list_of_dfs[[my_seqs[i]]]), sep = "_")
}
# Binding the columns from the aggedsite table (after setting wpp as an object) to the other aggregate tables
scored_data_site <- cbind(wpp,
list_of_dfs$site_avg[,-which(names(list_of_dfs$site_avg) %in% c("site_avg_wpp"))],
list_of_dfs$site_st[,-which(names(list_of_dfs$site_st) %in% c("site_st_wpp"))] )
## Main SIT Table: All turbine avgs, standard deviations, and site averages and standard deviations.
library(dplyr)
parent_df <- left_join(scored_data, scored_data_site, by = "wpp")
# Creating variables to keep the for-loop dynamic in the case that changes need to be made.
# Finding the number of columns associated with the tags. This will aid in calculating statistics.
tag_length <- length(df_turbinefilter[,-which(names(pidata) %in% c("wpp", "wt"))])
# Finding the first index column number where the condition is met. This is how the for loop will start.
tag_start <- which.max(!(names(parent_df) %in% c("wpp","wt")))
length_before_calcs <- length(parent_df)
## PERFORMING STATISTICAL CALCULATIONS AND ADDING NEW COLUMNS: WTG Avg-Site Avg/(Site St.Dev ^2/WTG St. Dev)
for (i in tag_start:tag_length) {
parent_df[,ncol(parent_df) + 1] <-
(parent_df[,i]-parent_df[,i+2*tag_length])/((parent_df[,i+3*(tag_length)])^2/parent_df[,i+(tag_length)])
names(parent_df)[ncol(parent_df)] <- paste0("Z_Score_",names(parent_df[i]))
}
## ADDING AN ALARM LEVEL COLUMN (0, 1, 2) DEPENDING ON THE CURRENT Z_SCORE
for (i in (length_before_calcs+1):ncol(parent_df)) {
parent_df[,ncol(parent_df) + 1] <-
ifelse(abs(parent_df[,i])<1, 0,ifelse(1<=abs(parent_df[,i]), 1, ifelse(abs(parent_df[,i]) >=2,2,0)))
names(parent_df)[ncol(parent_df)] <- paste0("Alarm_Level_", names(parent_df[i]))
}
OutputDataSet <- parent_df'
,@input_data_1 = N''
insert into SIT_WTG(
Date,
Park,
Turbine,
avg_wtgp_kw,
avg_metwndspd_ms,
avg_metextmp_degc,
st_wtgp_kw,
st_metwndspd_ms,
st_metextmp_degc,
site_avg_wtgp_kw,
site_avg_metwndspd_ms,
site_avg_metextmp_degc,
site_st_wtgp_kw,
site_st_metwndspd_ms,
site_st_metextmp_degc,
Z_Score_avg_wtgp_kw,
Z_Score_avg_metwndspd_ms,
Z_Score_avg_metextmp_degc,
Alarm_Level_Z_Score_avg_wtgp_kw,
Alarm_Level_Z_Score_avg_metwndspd_ms,
Alarm_Level_Z_Score_avg_metextmp_degc)
select @startdate as Date , *
from #temp_results t
drop table #temp_results