SQL Server中的Python:INT列中的NULL值映射到-2147483648而不是None

时间:2018-04-19 12:25:23

标签: python sql-server stored-procedures sql-server-2017

TL;博士

我在SQL Server 2017中使用Python .Python代码包含在我传递查询的存储过程中。查询得到评估,数据传递给Python。如果查询中的字符串列(char,nchar,varchar,nvarchar)包含NULL,则它将在Python中映射到None。但如果int列包含NULL,则会将其映射到-2147483648(我猜最小整数值)。

我的问题是如何在NULL列中将int值设为None,而不是-2147483648?该列需要保留int

可再现的例子

我正在使用的测试数据:

CREATE TABLE [dbo].[test_table](
    [a-string] [nvarchar](50) NULL,
    [a-date] [date] NULL,
    [a-int] [int] NULL,
    [a-null-int] [int] NULL,
    [a-null-str] [nvarchar](50) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[test_table] ([a-string], [a-date], [a-int], [a-null-int], [a-null-str]) VALUES (N'asdf', CAST(N'2018-04-11' AS Date), 1, NULL, NULL)
INSERT [dbo].[test_table] ([a-string], [a-date], [a-int], [a-null-int], [a-null-str]) VALUES (N'fdsa', CAST(N'2008-04-11' AS Date), 2, NULL, NULL)
INSERT [dbo].[test_table] ([a-string], [a-date], [a-int], [a-null-int], [a-null-str]) VALUES (N'Bob "Bla" Bob', CAST(N'2028-04-11' AS Date), 3, NULL, NULL)
INSERT [dbo].[test_table] ([a-string], [a-date], [a-int], [a-null-int], [a-null-str]) VALUES (N'Bob, Bob', CAST(N'2038-04-11' AS Date), 4, NULL, NULL)
INSERT [dbo].[test_table] ([a-string], [a-date], [a-int], [a-null-int], [a-null-str]) VALUES (N'Bob bob', CAST(N'1998-04-11' AS Date), 5, 1, NULL)

最后两列包含一些NULL值。第一个类型为int,第二个类型为nvarchar

存储过程的代码:

CREATE PROCEDURE [dbo].[usp_test]
    @query NVARCHAR(max)
AS
BEGIN
EXEC sp_execute_external_script 
@language = N'Python', 
@script = N'
print(InputDataSet)
',
@input_data_1 = @query
END;

存储过程有一个带有查询的参数,该查询将查询结果传递给Python代码。在Python代码中我打印数据。

我如何执行存储过程:

EXEC [dbo].[usp_test] N'SELECT [a-string],CAST([a-date] as nvarchar(20)) as [a-date],[a-int],[a-null-int],[a-null-str] FROM [dbo].[test_table]'

结果是:

        a-string      a-date  a-int  a-null-int a-null-str
0           asdf  2018-04-11      1 -2147483648       None
1           fdsa  2008-04-11      2 -2147483648       None
2  Bob "Bla" Bob  2028-04-11      3 -2147483648       None
3       Bob, Bob  2038-04-11      4 -2147483648       None
4        Bob bob  1998-04-11      5           1       None

意外行为位于a-null-int列中。在None逗留期间,如何将其设为-2147483648而不是int

这个问题与SQL Server密切相关。根据Microsoft的this documentation,BxlServer或SQL Satellite(不确定)处理SQL Server和Python之间的数据传输。我希望问题出在其中一项服务中。但我不知道如何规避它。

研究完成:

EDIT1;这个问题是否与问题How to store empty value as an Integerfield重复?

IMO没有。似乎问题是数据类型之间存在差异(str vs int)。这不是这种情况。如果我检查数据类型,我得到:

print(type(InputDataSet.ix[0,"a-null-int"]))
>>> <class 'numpy.int32'>

这是对的。我正在传递int列,并将其映射到python int。但我需要的是None

EDIT2;回复@ arun-gurunathan回答:

在开始之前,我需要说明[a-null-int]列需要保持整数类型。对于上下文,我需要将数据导出为CSV。为了说明我的问题,我将[a-null-int]列中最后一行的值从NULL更改为1。相应地改变了问题的开头。

使用RxMissingValues.int32(),我得到用于替换NULL值的值,即-2147483648。我可以用numpy.NaN替换这些值。它不是防弹修复,因为如果SQL Server中的列包含这个值会发生什么?然而,我继续走这条路......

我在上面的存储过程中输入了以下代码:

import numpy
from revoscalepy import RxMissingValues
InputDataSet.loc[InputDataSet["a-null-int"] == RxMissingValues.int32(), ("a-null-int")] = numpy.NaN
print(InputDataSet)

这是我的(缩写):

   a-null-int
0         NaN
1         NaN
2         NaN
3         NaN
4         1.0

[a-null-int]列转换为floatpandas doc中记录了此行为,并已在stackoverflow上进行了讨论。

由于处理NA值的NumPy限制,我希望我的问题无法解决。我还会再等一下,看看是否有更多的答案可以告诉我如何将列a-null-int的类型保持为int,或者一些解决方法。否则我会接受@ arun-gurunathan回答。

1 个答案:

答案 0 :(得分:1)

rxMissingValues document描述了在整数列中存储None值的pandas / numpy限制。您可以通过检查缺失值(rxMissingValues.int32())来处理这些问题,如文档中所述。