postgresql

  • 常见的数据库连接字符串收集

    原文地址:http://blog.csdn.net/a125138/article/details/7982614 MySQL: String Driver="com.mysql.jdbc.Driver"; //驱动程序 String URL="jdbc:mysql://localhost:3306/db_name"; //连接的URL,db_name为数据库名 String Username="username"; //用户名 String P

    jdbc, postgresql, url, String, 数据库May 3

  • PostgreSQL用C完成存储过程例子

    目的:用C完成一个存储过程例子,存储过程实现对表某一段进行update. 准备工作 1.安装数据库 2.建立表test highgo=# create table test(id int, name text, label int); CREATE TABLE 3.建立C文件,C代码如下: #include "postgres.h" #include "executor/spi.h" #include "utils/builtins.h" #if

    postgresql, 存储过程April 27

  • jsp连接各种数据库大全

    现在有好多初学JSP的网友经常会问数据库怎么连接啊,怎么老出错啊?所以我集中的在这写篇文章供大家参考,其实这种把数据库逻辑全部放在jsp里未必是好的做法,但是有利于初学者学习,所以我就这样做了,当大家学到一定程度的时候,可以考虑用MVC的模式开发.在练习这些代码的时候,你一定将JDBC的驱动程序放到服务器的类路径里,然后要在数据库里建一个表test,有两个字段比如为test1,test2,可以用下面SQL建 create table test(test1 varchar(20),test2 va

    jdbc, jsp, postgresql, String, 数据库, ScrollApril 20

  • postgresql事务提交失败导致锁表的解决办法
    postgresql事务提交失败导致锁表的解决办法

    这两天公司项目动不动就出问题,开始是无法登录,再过一段时间就访问不了了,出现如下情况: 起初以为是代理出现了问题,试着在网上找了下解决办法: 修改httpd.conf,在VirtualHost里加上 <VirtualHost *:80> ProxyPass http://192.168.145.111:7001/cd/ SetEnv force-proxy-request-1.0.1 SetEnv proxy-nokeepalive 1 </VirtualHost *:80> 保存

    postgresql, 数据库, 死锁, 事务April 3

  • 基于postgresQL的API设计

    基于postgresQL的API设计 本文档设计思想主要是用于简化API一些重复验证工作,同时固定API入口, 在入口中做请求分发, 以便在入口做一些统计工作以及请求次数限制. -- function api_interface(in jsonb, out jsonb); --入口函数(存储过程) api_interface_error(code); -- 统一错误处理函数 api_interface_lines(user_id, params, team_id); --线路列表例子 --tab

    api, postgresqlMarch 12

  • postgresql数据类型之Serial

    概述 一般来说,每一个都需要一个主键,主键的值一般是通过数据库的auto_increment或者使用插入sequence来保证每条记录分配唯一的值. Oracle在12c中实现了表中序列的auto_increment,12c之前只能通过trigger来自己实现. PG中有个数据类型serial. 创建带serial的表 创建和使用 db01=# create table t_t3(id serial,name varchar(30)); CREATE TABLE db01=# insert in

    postgresql, sequence, serial, 自增长序列March 9

  • postgresql数据类型之混合类型

    概述 这种有点像java中的class,c中的struct oracle中的object类型或者在pl/sql中的record类型. 创建composite type 我们测试使用一下pg中的这个数据类型 db01=# create type my_point as (x int,y int); CREATE TYPE db01=# create table my_position(id int,w my_point); CREATE TABLE db01=# \d my_position Ta

    postgresql, 数据类型, type, Record, Composite, RowMarch 6

  • postgresql事务隔离级别(二)

    Repeatable read 在这个隔离级别测试一下不可重复读和幻读 --session1 db01=# begin; BEGIN db01=# set transaction isolation level repeatable read; SET db01=# select * from t1 where id = 3; --pg会根据此查询获取相应的snapshot. 3 | aaaaaa db01=# select count(*) from t1; 10 --session2 db0

    postgresql, 脏读, 不可重复读, 幻读, 事务, 隔离级别March 5

  • postgresql事务隔离级别(一)

    隔离级别 在讲隔离级别前,要先知道事务中会发生的三种现象 脏读(dirty read)-当前事务可以读取到另一个事物未提交的数据 不可重复读(nonrepeatable read)-当前事务中重复读取同样的数据,发现读取的数据已经被另一个事物修改而得到了不同的结果 幻读(phantom read)-当前事务中重复执行相同的查询,返回的记录数因另一个事物插入或删除而得到不同的结果 在sql标准中定义了4种隔离级别,并且必须要满足相应的条件 隔离级别 脏读 不可重复读 幻读 Read uncommi

    postgresql, 脏读, 不可重复读, 幻读, 事务, 隔离级别March 5

  • 解决Hibernate不支持PostgreSQL中双冒号(::)的Bug

    在PostgreSQL中,双冒号(::)的作用是类型转换,而在Hibernate中,SQL中冒号的作用是命名参数,用于SQL中命名参数的匹配,这时,当在PostgreSQL数据库环境中,正常的SQL本身包括双冒号时,通过Hibernate进行查询就会报错,这个应该是Hibernate的一个Bug,怎么解决呢,本文将给出方案. 通过研究Hibernate的源代码,发现了问题所在,问题出在org.hibernate.engine.query.spi.ParameterParser,这个类构造方法为私

    postgresql, Hibernate, 双冒号, 不支持双冒号March 5

  • postgresql部分索引(Partial index)

    主要是在满足条件的部分上建立索引,特别情况下的索引效率会很高. 创建partial index db01=# create table t_index(id int,name varchar(30)); CREATE TABLE db01=# insert into t_index select generate_series(1,1000),'name'; INSERT 0 1000 db01=# insert into t_index select generate_series(1001,

    postgresql, 优化, Partial, index, 部分索引March 4

  • postgresql表记录返回函数

    数组中有一些类似的函数比如unnest也会返回表记录集,这里主要将两个函数 generate_series int,bigint 入参 db01=# select generate_series(1,6); generate_series ----------------- 1 2 3 4 5 6 (6 rows) db01=# select generate_series(1,6,2); generate_series ----------------- 1 3 5 (3 rows) db01

    postgresql, with, generate_series, generate_subscripts, ordinalityMarch 3

  • postgresql数组相关函数

    数组间操作 数组比较和包含 数组相等 db01=# select array[1.1,2.2,3.3]::int[] = '{1,2,3}'::int[]; t 两个数组相同下标下的元素值全部相等,则认为这个数组相等. 数组大小包含 db01=# select array[1,2,3] < array[2,3],array[1,2,3] @> array[2,3]; t | t 比较有大>,<,>=,<= @>包含是指数组A里有数组B的所有元素,即使数组A=B,@

    array, postgresql, 函数, 数组March 2

  • postgresql数据类型之数组类型

    数组字段类型 db01=# create table t_array(id int,array_1 int[],array_2 text[][]); CREATE TABLE db01=# \d t_array Table "hippo.t_array" Column | Type | Modifiers ---------+-----------+----------- id | integer | array_1 | integer[] | array_2 | text[] | 虽

    array, postgresql, 数组March 2

  • postgresql数据类型之枚举类型及相关函数

    enum的使用 db01=> create type enum_clor as enum ('red','black','green','white','blue'); CREATE TYPE db01=> create table t_pencil(id int,clor enum_clor); CREATE TABLE db01=> insert into t_pencil values(1,'red'); INSERT 0 1 db01=> insert into t_pen

    postgresql, enum, 枚举March 1

  • postgresql时间相关函数

    时间与字符串转换 to_char postgres=# select to_char(timestamp'now','yyyy-mm-dd hh24:mi:ss.ssssss'),to_char(timestamp'now','hh24:mi:ss'); 2015-02-28 23:59:15.8635515 | 23:59:15 按照给定的格式输出 to_date, to_timestamp postgres=# select to_date('2013-11-11','yyyy-mm-dd'

    postgresql, interval, timestamp, 函数, 时间, date, time()February 28

  • postgresql数据类型之时间类型

    date postgres=# select date'2015-2-28',date'2015-2-28 12:22:30'; date | date ------------+------------ 2015-02-28 | 2015-02-28 (1 row) 日期只有年月日 time postgres=# select time '000001.111',time'24:00:00',time '2013-11-11 11:23:44'; time | time | time ----

    postgresql, 时间, 时间戳, 日期, 数据类型February 28

  • 用Pgpool-II实现Postgresql高可用集群

    其实整个安装和配置过程比较简单,官方网站有比较好的文档,在此只是根据前几天的实际部署整理一下.(实际执行的命令都用红色标出) 服务器: 10.18.27.181 pgpool服务器 --------此服务器上需要安装pgpool和pg 10.18.27.183 data node 1 --------此服务器上安装pg 10.18.27.184 data node 2 --------此服务器上安装pg 10.18.27.185 data node 3 --------此服务器上安装pg 10.

    postgresql, 集群, 高可用, pgpool-IIFebruary 27

  • postgresql高可用性之备库(四)

    概述 如果一旦主库宕机,pg提供了机制,使备机变成主机提供服务. 为了使主备库可以相互切换,我们需要进行修改一些配置. 配置主库 在主库上配置一旦变成备库的时候所需要使用的参数 修改服务配置文件 [[email protected] data]$ vi postgresql.conf hot_standby = on 主要是变成备库后需要打开hot_standby,其他之前已经配置好 准备好 recovery.conf [[email protected] data]$ scp 192.168.10.72:

    postgresql, replication, dataguard, 高可用, streaming, 流复制, 备库, hot-standby, log-shippingFebruary 27

  • postgresql高可用性之备库(三)

    流复制的归档相关设置 流复制对于主库是不是开启归档没有必然的联系. 开启归档对于做基础备份和恢复是必要的. 如果主库开启归档,并且归档目录备库可以访问到的话,在备库启动时的工作方式为: 首先使用restore_command尽可能使用WAL归档来恢复. 上面命令返回失败,则再在xlog目录下应用可以使用的 上面步骤应用完之后,如果开启了流复制,尝试连接主库,并一直使用流复制方式进行准实时同步- 如果流复制连接失败或者没有开启流复制,则回到第一步如此循环. 关闭主库归档 归档在灾难恢复时用来恢复是

    postgresql, replication, dataguard, 高可用, streaming, 流复制, 备库, hot-standby, log-shippingFebruary 27

  • postgresql高可用性之备库(二)

    概述 由于基于WAL归档搭建的备库,实时性不太好 而streaming replication可以将备库跟主库数据同步差异缩小至最小,实用性更好一点 这篇主要将上一篇的配置进行修改,使变成流复制的模式运行 主库修改配置 添加一个复制用户 postgres=# create role repl replication login password 'postgres'; CREATE ROLE 修改postgres.conf [[email protected] data]$ vi postgresql

    postgresql, replication, dataguard, 高可用, streaming, 流复制, 备库, hot-standby, log-shippingFebruary 27

  • postgresql字符串函数与操作符号(二)

    trim 函数相关 db01=> select trim(leading 'x' from 'xxTxTxx'),trim(trailing 'x' from 'xxTxTxx'),trim(both 'x' from 'xxTxTxx'),trim('x' from 'xxTxTxx'); TxTxx | xxTxT | TxT | TxT 单独的函数 db01=> select ltrim('xxTxTxx','x'),rtrim('xxTxTxx','x'),btrim('xxTxTxx

    postgresql, 字符串, 函数, 正则表达式, 符号February 25

  • postgresql字符串函数与操作符号(一)

    字符串拼接 使用 || 拼接 db01=> select 'sss' || 'aaa','sss' || 123; sssaaa | sss123 db01=> select 111 || 222; ERROR: operator does not exist: integer || integer LINE 1: select 111 || 222; ^ HINT: No operator matches the given name and argument type(s). You mi

    postgresql, 字符串, 函数, 符号February 25

  • postgresql数学函数与操作符

    数学操作符 取模,绝对值 db01=> select 20%3,@ 10,@ -10; -- @和-要有个空格 2 | 10 | 10 幂 db01=> select 2^8; 256 平方根,三次方根 db01=> select |/2,||/27; 1.4142135623731 | 3 那四次方根,五次方根怎么搞?用幂来搞! db01=> select 16 ^ (1.0/4),32 ^ (1.0/5); 2.00000000000000000000 | 2.00000000

    postgresql, 函数, 符号, 数学February 25

  • postgresql 逻辑和比较操作

    逻辑操作 需要注意跟null值的与或操作 db01=> select true and null,true or null; ?column? | ?column? ----------+---------- | t (1 row) db01=> select false and null,false or null; ?column? | ?column? ----------+---------- f | (1 row) 比较操作 between 比较中,and两边的值是包括进去的.这里需

    postgresql, BETWEEN, is_distinct_fromFebruary 24

  • postgresql中表的继承及分区表(三)

    分区表管理 按照时间来分区的分区表的典型使用场景是: 某一段时间之前的数据进行归档备份 时间要超过分区表最大限制时增添新的分区 这样做的好处是,你的主表不管多久,数据量总是保持相同的水平.不会随着时间推移查询越来越慢 添加新分区 db01=> create table t_partition_s200504 (check(log_date >= '2015-4-1' and log_date < '2015-5-1')) inherits (t_partition); CREATE TA

    inheritance, postgresql, 分区表, 表继承February 24

  • postgresql中表的继承及分区表(二)

    概述 在PG中分区表是通过表的继承来实现的. 父表描述表结构.多个子表继承同一个父表,通过trigger或rule来实现对这分区表的各种DML操作. 详细操作我们通过一个例子来表示 创建分区表 这里我准备创建一个按照日期字段来分区的分区表.每个分区只存放一个月的数据. 创建主表(父表) db01=> create table t_partition( db01(> id int not null, db01(> msg text, db01(> log_date date not

    inheritance, postgresql, 分区表, 表继承February 24

  • postgresql中表的继承及分区表(一)

    表的继承 示例 db01=> create table t_parent(id int,name varchar(30)); CREATE TABLE db01=> create table t_child(flag boolean) inherits(t_parent); CREATE TABLE 制造数据 db01=> insert into t_parent values(1,'hippo1'); INSERT 0 1 db01=> insert into t_parent

    inheritance, postgresql, 分区表, 表继承February 24

  • postgresql中的查询(query)二

    with查询有点像临时表,一般用在复杂查询中,需要多次使用到这个查询结果时. with还有个用处是递归查询.oracle 11gR2开始也支持了. PG中的DML也可以使用with语句.我们来依次看看. with普通用法 db01=> with t as ( select * from t_insert ) select count(*) from t; count ------- 7 (1 row) 只是作为最简单的示例:) with recursive 递归查询 用来制造测试数据 使用gen

    postgresql, cte, 查询, 递归, with, 树状, query, recursiveFebruary 24

  • postgresql中DML操作

    除了insert我感觉有些特别的写法.update和delete没啥特别的. 这里列举一些特殊的写法 insert db01=> create table t_insert(id int,name text); CREATE TABLE db01=> insert into t_insert values(1,'hippo'); INSERT 0 1 db01=> insert into t_insert values(2,'jack'),(3,'joe'),(4,'alice'); -

    postgresql, dml, insert特殊写法February 22

  • postgresql中schema概念

    schema概念有点像命名空间或者把它想像成一个文件系统中的目录,差别就是这个schema下不能再有schema嵌套. 各个对象比如表,函数等存放在各个schema下,同一个schema下不能有重复的对象名字,但在不同schema下可以重复. 使用schema的作用 方便管理多个用户共享一个数据库,但是又可以互相独立. 方便管理众多对象,更有逻辑性 方便兼容某些第三方应用程序,创建对象时是有schema的 比如要设计一个复杂系统.由众多模块构成,有时候模块间又需要有独立性.各模块存放单独的数据库

    schema, postgresql, 用户, 权限February 22

  • postgresql在线备份与恢复(三)

    备份一个基础备份,使用底层API 确保你已经开启了归档 可以通过检查参数设置,找到归档目录,手动切换wal日志来查看是否可以正确归档 postgres=# select name,setting from pg_settings where name like 'archive%' or name = 'wal_level'; name | setting -----------------+----------------------------------------------------

    postgresql, timeline, 备份恢复, pitr, 时间点恢复February 13

  • PostgreSQL导出导入schema相关

    整理了一下PostgreSQL导入导出相关schema的方法. 一.导出: 导出his库里crm的schema表结构和数据(-n参数): pg_dump -h 192.168.2.154 -p 5432 -d his -n crm -f test.sql 只导出his库里crm的schema表结构(-s参数): pg_dump -h 192.168.2.154 -p 5432 -d his -n crm -s -f test2.sql 二.导入不同schema中 先导出crm库里的crm的sch

    schema, postgresql, RestoreFebruary 11

  • postgresql 修改日志输出

    修改服务配置文件 我准备配置成这样: 输出格式为csv,这样可以方便使用或者导入到表中查询. 日志只保留一个月. 每天至少新生产一个日志. 一旦一个日志满100M,就生成新的日志文件,防止过大. 修改下列参数并重启生效: [[email protected] pgsql]$ cd $PGDATA [[email protected] data]$ vi postgresql.conf ...... log_destination = 'csvlog' # Valid values are combinati

    postgresql, 日志, log, RotationFebruary 11

  • postgresql备份恢复之pg_dump大数据处理

    介绍 官方文档介绍的主要有三种方式: 通过unix管道,直接读取pg_dump的输出来压缩. 使用pg_dump的custom-format 使用pg_dump的directory-format 使用管道压缩和解压 由于pg_dump工具可以输出到标准输出,可以使用unix管道来直接压缩 1.压缩方法 [[email protected] ~]$ pg_dump database1 | gzip > database1.sql.gz 还原 [[email protected] ~]$ createdb -T

    postgresql, database, backup, Large, pg_dump, pg_restore, 大数据备份恢复February 10

  • postgresql备份与恢复之SQL Dump

    数据是很宝贵的,要时候谨记备份的重要性. 这里讲一下通过SQL Dump方式来做备份与恢复. pg_dump 导出某一个数据库,通过将数据库中的结构信息及数据通过sql方式输出来备份数据库.它是在执行命令那一刻时数据库一致性状态的保存. 恢复时只许将这输出在目标库上重建就可以了. 使用pg_dump命令备份 pg_dump 默认输出到控制台,不指定参数默认是导出连接着的数据库. [[email protected] data]$ pg_dump | more -- -- PostgreSQL data

    postgresql, 恢复, 数据库备份, pg_dumpFebruary 10

  • postgresql role(角色)

    在PG中,角色与用户的概念比较模糊,可以认为带LOGIN属性的role就是用户. 创建role 带了login属性.就可以登录数据库. postgres=# create role role1; CREATE ROLE postgres=# \c - role1 FATAL: role "role1" is not permitted to log in Previous connection kept postgres=# alter role role1 login; ALTER

    postgresql, 用户, 角色, roleFebruary 9

  • postgresql升级-小版本号升级

    今天发现更新了9.4.1,正好更新一下 根据官方文档,小版本号不需要做复杂操作,只需要用新的二进制文件替换掉原来的. 数据等不需要操作. 大版本号升级要复杂一点,等新版本出来后再记录吧. 使用postgres用户停止数据库 [[email protected] data]$ pg_ctl stop waiting for server to shut down.... done server stopped 下载源码并编译安装 [[email protected] ~]# wget https://ftp.post

    postgresql, 升级, upgrade, 小版本February 6

  • postgresql中表空间管理

    表空间作为数据库对象存放的地方,对于数据库来说是个逻辑概念,它是文件系统中一个目录下的多个数据文件组成. 目录可以不存放在PGDATA下,但是是作为cluster的一个部分,如果备份需要一起备份. 创建表空间 只能使用superuser来创建表空间 postgres=# create tablespace ts01 location '/var/lib/pgsql/tsdata'; ERROR: directory "/var/lib/pgsql/tsdata" does not ex

    postgresql, tablespace, 表空间管理February 6

  • postgresql中数据库database的管理

    PG中database的概念 不像oracle中一个或多个实例只管理一个DB,在PG中一个实例下有一个database cluster,可以管理多个DB,一个DB下有多个schema,schema下有各种数据库对象如table,index等等. 有些系统视图比如pg_database等属于cluster层级 创建DB 先检查下目前的数据库,2种方法 postgres=# select datname from pg_database; datname ----------- template1

    postgresql, 管理, database, templateFebruary 6

  • Python发邮件示例

    最近在同事的帮助下,尝试着用python写了一个发送邮件的小工具,可以省去配置mailrc参数的麻烦. 以下是示例: [[email protected] scripts]# more sendmail.py #!/usr/bin/env python2 #coding: utf-8 import smtplib import datetime from email.mime.text import MIMEText from email.header import Header from emai

    postgresql, python, MonitorFebruary 6

  • postgresql的substr()函数

    select substr('1234',0,3) as re 如果是pg:得到的结果是12 如果是oracle:得到的结果是123 如果是mysql:得到的结果是空 因为pg和mysql的substr()函数的第一个位置都是为1的,pg为0的时候返回数据是有值的,但mysql为0时候返回数据为空了

    oracle, postgresql, MySQLFebruary 5

  • 外部客户端连接postgresql相关设置
    外部客户端连接postgresql相关设置

    修改服务配置文件postgresql.conf中的监听参数 默认配置文件在PGDATA目录下(除了你是通过服务进程中的参数config_file来指定的) [[email protected] data]$ vi postgresql.conf ...... listen_addresses = '*' # what IP address(es) to listen on; ...... 修改pg_hba.conf文件,添加一行host认证 默认配置文件在PGDATA目录中,可以通过服务配置文件 po

    postgresql, 客户端, 连接配置February 4

  • postgresql 在linux上的源码安装

    下载源码并解压 [[email protected] ~]# wget https://ftp.postgresql.org/pub/source/v9.4.0/postgresql-9.4.0.tar.bz2 [[email protected] ~]# tar -xjvf postgresql-9.4.0.tar.bz2 [[email protected] ~]# cd postgresql-9.4.0 开始编译安装 [[email protected] postgresql-9.4.0]# ./configure -- checking fo

    postgresql, 安装, 源码, InstallFebruary 4

  • postgresql 查看数据库,表,索引,表空间以及大小

    1,查看数据库 \l //\加上字母l,相当于mysql的,mysql> show databases; select pg_database_size('playboy'); //查看playboy数据库的大小,playboy是数据库名称 select pg_database.datname, pg_database_size(pg_database.datname) AS size from pg_database; //查看所有数据库的大小 select pg_size_pretty(pg

    postgresql, 查看数据库, 查看表, 查看索引, 查看表空间February 4

  • Bucardo的状态问题

    用Bucardo做PostgreSQL的双主或者主从是,比如A服务器部署了bucardo,向B服务器近实时同步A服务器的数据,假如B服务器挂了,会影响Bucardo的状态.但是这个状态需要细化才能发下. 一. 环境: PostgreSQL 9.3.5 Bucardo 5.3.0 A与B通过Bucardo做同步 二.状态监测 --停掉B服务器的DB,能看到sync_adm的状态还是好的,这是假象 [[email protected] ~]$ bucardo status PID of Bucard

    postgresql, bucaroJanuary 23

  • nodejs+grunt+mocha+express+postgres搭建开发环境

    nodejs/bower/grunt/mocha/express/postgres搭建开发环境 0. nodejs 流行的异步IO解决方案,链接[http://nodejs.org/](http://nodejs.org) 1. bower 前段框架管理工具 2. grunt 自动化工具[gruntjs.com](gruntjs.com) 3. mocha 自动化单元测试[http://mochajs.org/](http://mochajs.org) 4. express nodejs界最有名

    postgresql, bower, grunt, nodejs, mochaJanuary 21

  • PostgreSQL的索引选型

    PostgreSQL里面给全文检索或者模糊查询加索引提速的时候,一般会有两个选项,一个是GIST类型,一个是GIN类型,官网给出的参考如下: There are substantial performance differences between the two index types, so it is important to understand their characteristics. A GiST index is lossy, meaning that the index ma

    postgresql, gist, ginJanuary 16

  • PostgreSQL on Ubuntu Linux

    PostgreSQL is a powerful object-relational database management system, provided under a flexible BSD-style license. PostgreSQL contains many advanced features, is very fast and standards compliant. It supports a large part of the SQL standard and is

    postgresql, ubuntu, pgadmin, command, database, terminalJanuary 13

  • PostgreSQL给模糊搜索加索引

    PostgrSQL有个模块叫pg_trgm,可以对字符串来进行比较相似度,并通过加GIST或者GIN索引来达到提速的效果.在一般的RDBMS中这种需求都会进行全表扫描的,但是PG如果加了这个模块,在一定场景下就可以使用索引来提速了. 一.背景 我们有一个需求根据人员的拼音码(或者药品的拼音码)进行搜索,因为拼音码不一定是全的,故通常给的方案是模糊搜索,在拼音码的首尾两端各加一个百分号,但是效率通常很慢,一般情况下也不建议这么做. 二.环境 OS:CentOS 6.5 DB:PostgreSQL

    postgresql, gist, pg_trgmJanuary 12