3. Data Types
• Boolean (!)
• Numeric
• up to 131072 digits before decimal;
16383 digits after (MySQL: 65 digits)
• Network address
broadcast('192.168.1.5/24')
hostmask('192.168.23.20/30')
• UUID
• XML
• Geometric (point, line, rectangle, circle,
path, polygon)
• JSON (in 9.2, later in 2012)
4. Data Types
• Make your own!
CREATE TYPE inventory_item AS (
! name text,
! supplier_id integer,
! price numeric);
CREATE TABLE on_hand (
! item inventory_item,
! count integer);
INSERT INTO on_hand VALUES (ROW('fuzzy dice', 42, 1.99), 1000);
SELECT (on_hand.item).name FROM on_hand WHERE (on_hand.item).price > 9.99;
5. Custom Functions
CREATE FUNCTION price_extension(
! inventory_item,
! integer)
RETURNS
! numeric
AS '
! SELECT
! ! $1.price * $2'
LANGUAGE SQL;
SELECT price_extension(item, 10) FROM on_hand;
8. Functions! (Text Search)
• Very fast index updates • Search terms in context
(shows how your search
• Proximity terms are used in
• Weighting scheme context)
• Stemming • Regex, substring etc
• Stopwords
• Modular architecture
(add parsers and
dictionaries)
• Multilingual support
9. Functions! (Text Search)
• Very fast index updates • Search terms in context MySQL:
(shows how your search
• Proximity terms are used in Regex, substring, etc
• Weighting scheme context)
• Stemming • Regex, substring etc
• Stopwords
• Modular architecture
(add parsers and
dictionaries)
• Multilingual support
12. Functions! (Window Functions)
Any aggregate function:
SELECT name, salary, salary / (avg(salary) OVER (PARTITION BY depname)) FROM employee
13. Functions! (Window Functions)
Any aggregate function:
SELECT name, salary, salary / (avg(salary) OVER (PARTITION BY depname)) FROM employee
Special window functions:
SELECT name, rank() OVER (PARTITION BY department_id ORDER BY hire_date ASC) FROM employee
26. Small but big features
• Index in the background
• Transactional schema changes
27. Small but big features
• Index in the background
• Transactional schema changes
• Fast schema changes
28. Small but big features
• Index in the background
• Transactional schema changes
• Fast schema changes
• Drop column instantly
29. Small but big features
• Index in the background
• Transactional schema changes
• Fast schema changes
• Drop column instantly
• Add column instantly (unless default value)
32. NoSQL in your SQL (Arrays)
SELECT * FROM sal_emp;
name | pay_by_quarter | schedule
-------+---------------------------+-------------------------------------------
Bill | {10000,10000,10000,10000} | {{meeting,lunch},{training,presentation}}
Carol | {20000,25000,25000,25000} | {{breakfast,consulting},{meeting,lunch}}
(2 rows)
SELECT name FROM sal_emp WHERE pay_by_quarter[1] <> pay_by_quarter[2];
name
-------
Carol
(1 row)
33. NoSQL in your SQL (Arrays)
SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill';
schedule
------------------------
{{meeting},{training}}
(1 row)
SELECT * FROM sal_emp WHERE 10000 = ANY (pay_by_quarter);
ARRAY[1,4,3] @> ARRAY[3,1]
34. NoSQL in your SQL (Arrays)
SELECT
! buyer,
! SUM(total),
! ARRAY_AGG(order_date ORDER BY total DESC)
FROM
! orders
GROUP BY
! buyer;
buyer | sum | array_agg
------+------+-------------------------------------------------------------------
Alice | 1057 | {2009-05-08,2009-08-15,2009-03-25,2009-08-16}
Bob | 905 | {2009-02-10,2009-01-29,2009-08-17,2009-05-12,2009-08-22,2009-05-28}
Carol | 1118 | {2009-04-28,2009-09-01,2009-03-30,2009-06-27-01-10,2009-09-06}
Dave | 1239 | {2009-05-28,2009-07-27,2009-02-07,2009-07-15,2009-08-27}
Eve | 1222 | {2009-02-01,2009-08-14,2009-09-26,2009-04-07-10-02}
(5 rows)
35. NoSQL in your SQL (HStore)
Key-value store:
create_table :products do |t|
! t.string :name
! t.hstore :data
! t.timestamps
end
gem install activerecord-postgres-hstore
Product.create(
! name: "Geek Love: A Novel",
data: {'author' => 'Katherine Dunn', 'pages' => 368, 'category' => 'fiction'})
Product.last.data['category'] # => 'fiction'
36. NoSQL in your SQL (HStore)
# Find all products that have a key of 'author' in data
Product.where("data ? :key", :key => 'author')
# Find all products that have a 'pages' and '368' key value pair in data
Product.where("data @> (:key => :value)", :key => 'pages', :value => '368')
# Find all products that don't have a key value pair 'pages' and '999' in data
Product.where("not data @> (:key => :value)", :key => 'pages', :value => '999')
# Find all products having key 'author' and value like 'ba' in data
Product.where("data -> :key LIKE :value", :key => 'author, :value => "%Kat%")
37. Use a really good language
CREATE FUNCTION tu(varchar)
RETURNS setof record
AS '
! size = PL.column_name(args[0]).size
! res = nil
! PL::Plan.new("select * from #{args[0]}", 'block' => 50).each do |row|
! ! if res.nil?
! ! ! res = row.values
! ! else
! ! ! res.concat row.values
! ! ! yield res
! ! ! res = nil
! ! end
! end
! if res
! ! res.concat Array.new(size)
! ! yield res
! end
' language 'plruby';
CREATE FUNCTION