数据值

PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 章 43. PL/Python - Python 过程语言 | 下一页

# 43.3. 数据值

一般来说，PL/Python的目的是提供PostgreSQL和Python世界之间的"自然"映射。 如下面描述的数据映射规则。

## 43.3.1. 数据类型映射

函数参数是从他们的PostgreSQL类型转换为相应的Python类型：

- PostgreSQL `boolean`转换成Python `bool`。

- PostgreSQL `smallint`和`int`转换成Python `int`。 PostgreSQL `bigint`和`oid`在Python 2中转换成`long`， 在Python 3中转换成`int`。

- PostgreSQL `real`和`double` 转换成Python `float`。

- PostgreSQL `numeric`转换成Python `Decimal`。 这个类型是从`cdecimal`包中引入的，如果该包可用的话。 否则将使用来自标准库的`decimal.Decimal`。 `cdecimal`比`decimal`明显快的多。 在Python 3.3中，`cdecimal`已经以`decimal` 的名字合并到标准库中了，所以不再有任何不同了。

- PostgreSQL `bytea`在Python 2中转换成Python `str`， 在Python 3中转换成`bytes`。在Python 2 中，字符串应被视为没有任何字符编码的字节序列。

- 所有其他数据类型，包括PostgreSQL字符串类型，转换为Python `str`。 在Python 2中，这个字符串将以PostgreSQL服务器编码；在Python 3中，它是一个Unicode字符串，和所有的字符串一样。

- 对于非标量数据类型，见下文。

函数的返回值被转换为声明的PostgreSQL返回数据类型，如下：

- 当PostgreSQL返回类型是`boolean`，按照Python 规则返回值估计为真。也就是说，0和空字符串是假，但值得注意的是`'f'`是真。

- 当postgreSQL返回类型是`bytea`时，返回值将使用各自的Python内建被转换成字符串 （Python 2）或者字节(Python 3)，其结果被转换成`bytea`。

- 对于所有其他PostgreSQL返回类型，返回的Python值使用Python内建`str` 转换成字符串，结果传递到PostgreSQL数据类型的输入函数。

  当在Python 2中的字符串要传递到PostgreSQL时，要求它们是以PostgreSQL服务器编码。 在当前服务器编码中无效的字符串将引发错误，但不是所有的编码不匹配都可以被检测到， 因此当做的不正确时，仍然会产生垃圾数据。Unicode字符串自动转换为正确的编码， 所以它可以更安全，更方便的使用。在Python 3中，所有的字符串都是Unicode字符串。

- 对于非标量数据类型，见下文。

请注意，PostgreSQL声明的返回类型和实际返回对象的Python数据类型之间的逻辑不匹配是不标记的； 该值将在任何情况下被转换。

## 43.3.2. Null, None

如果向函数传递了一个SQL null值，参数值在Python中将会显示为 `None`。比如，在第 43.2 节中显示的 `pymax`的函数定义对于null输入将返回错误结果。 我们可以添加`STRICT`到函数定义，使得PostgreSQL 进行更加合理的操作：如果传入null值，函数将根本不会被调用，而是立即自动返回null。或者， 也可以在函数体中检查输入参数是否为null:

    CREATE FUNCTION pymax (a integer, b integer)
      RETURNS integer
    AS $$
      if (a is None) or (b is None):
        return None
      if a > b:
        return a
      return b
    $$ LANGUAGE plpythonu;

如上所示，要从PL/Python函数中返回一个SQL null 值，返回`None`即可。 无论函数是否严格，这样做都有效。

## 43.3.3. Arrays, Lists

SQL数组值作为Python列表传递给PL/Python。要从PL/Python函数返回一个SQL数组值， 只需返回一个Python序列，例如一个列表或元组：

    CREATE FUNCTION return_arr()
      RETURNS int[]
    AS $$
    return (1, 2, 3, 4, 5)
    $$ LANGUAGE plpythonu;

    SELECT return_arr();
     return_arr
    -------------
     {1,2,3,4,5}
    (1 row)

注意:在Python中，字符串是序列，这可能有不良影响，这可能是Python程序员熟悉的：

    CREATE FUNCTION return_str_arr()
      RETURNS varchar[]
    AS $$
    return "hello"
    $$ LANGUAGE plpythonu;

    SELECT return_str_arr();
     return_str_arr
    ----------------
     {h,e,l,l,o}
    (1 row)

## 43.3.4. 复合类型

复合类型参数将作为Python映射传递给函数。映射的元素名是复合类型的属性名。 如果被传递行的某个属性是null值，那么它在映射中的值是`None`。下面是例子：

    CREATE TABLE employee (
      name text,
      salary integer,
      age integer
    );

    CREATE FUNCTION overpaid (e employee)
      RETURNS boolean
    AS $$
      if e["salary"] > 200000:
        return True
      if (e["age"] < 30) and (e["salary"] > 100000):
        return True
      return False
    $$ LANGUAGE plpythonu;

有多种从Python函数返回行或复合类型的方法。下面的例子假定我们有：

    CREATE TYPE named_value AS (
      name   text,
      value  integer
    );

一个复合类型结果可以作为下列之一返回：

序列类型（一个元组或列表，但不是一个集合，因为集合是不可以被索引的）

  返回的序列对象必须与复合结果类型字段数相同。索引为0的项将被分配给复合类型的第一个字段， 索引为1的项分配给第2个字段，以此类推。比如：

      CREATE FUNCTION make_pair (name text, value integer)
        RETURNS named_value
      AS $$
        return [ name, value ]
        # or alternatively, as tuple: return ( name, value )
      $$ LANGUAGE plpythonu;

  要为任何字段返回SQL null，就在相应的位置插入`None`。

映射（字典）

  每个结果类型字段的值从映射中使用字段名作为键检索，例如：

      CREATE FUNCTION make_pair (name text, value integer)
        RETURNS named_value
      AS $$
        return { "name": name, "value": value }
      $$ LANGUAGE plpythonu;

  任何额外的字典键/值对被忽略。丢失的键将被当作错误。要为任何字段返回SQL null值， 就以相应的字段名作为键插入`None`。

对象(任何提供`__getattr__`方法的对象)

  它的工作方式和映射一样，例如：

      CREATE FUNCTION make_pair (name text, value integer)
        RETURNS named_value
      AS $$
        class named_value:
          def __init__ (self, n, v):
            self.name = n
            self.value = v
        return named_value(name, value)

        # or simply
        class nv: pass
        nv.name = name
        nv.value = value
        return nv
      $$ LANGUAGE plpythonu;

也支持带有`OUT`参数的函数。例如：

    CREATE FUNCTION multiout_simple(OUT i integer, OUT j integer) AS $$
    return (1, 2)
    $$ LANGUAGE plpythonu;

    SELECT * FROM multiout_simple();

## 43.3.5. 设置返回函数

PL/Python函数也可以返回标量或者复合类型的集合。 有多种方法可以达到这个目的，因为返回对象在内部被转换成一个迭代器。 下面的例子假定我们有一个复合类型：

    CREATE TYPE greeting AS (
      how text,
      who text
    );

一个集合结果可以从下列之一返回：

序列类型（元组、列表、集合）

      CREATE FUNCTION greet (how text)
        RETURNS SETOF greeting
      AS $$
        # return tuple containing lists as composite types
        # all other combinations work also
        return ( [ how, "World" ], [ how, "PostgreSQL" ], [ how, "PL/Python" ] )
      $$ LANGUAGE plpythonu;

迭代器（任何提供`__iter__`和`next`方法的对象）

      CREATE FUNCTION greet (how text)
        RETURNS SETOF greeting
      AS $$
        class producer:
          def __init__ (self, how, who):
            self.how = how
            self.who = who
            self.ndx = -1

          def __iter__ (self):
            return self

          def next (self):
            self.ndx += 1
            if self.ndx == len(self.who):
              raise StopIteration
            return ( self.how, self.who[self.ndx] )

        return producer(how, [ "World", "PostgreSQL", "PL/Python" ])
      $$ LANGUAGE plpythonu;

生成器(`yield`)

      CREATE FUNCTION greet (how text)
        RETURNS SETOF greeting
      AS $$
        for who in [ "World", "PostgreSQL", "PL/Python" ]:
          yield ( how, who )
      $$ LANGUAGE plpythonu;

  警告
  由于Python bug #1483133的原因， 一些Python 2.4的调试版本(使用`--with-pydebug`选项配置和编译) 已知会让PostgreSQL服务器在使用迭代器返回集合时崩溃。 Fedora 4的应用补丁版本包含这个臭虫。但是在生产版本的Python或已经修补的Fedora 4上没有这个问题。

也支持带有`OUT`参数的设置返回函数（使用`RETURNS SETOF记录`）。 例如：

    CREATE FUNCTION multiout_simple_setof(n integer, OUT integer, OUT integer) RETURNS SETOF record AS $$
    return [(1, 2)] * n
    $$ LANGUAGE plpythonu;

    SELECT * FROM multiout_simple_setof(3);

上一页 | 起始页 | 下一页
PL/Python 函数 | 上一级 | 共享数据