diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,9 @@
 <!-- -*- Markdown -*- -->
 
+## 0.8.7.0
+
+- add NULLS FIRST and NULLS LAST to ORDER BY clause.
+
 ## 0.8.6.0
 
 - add Show instance of Pi.
diff --git a/relational-query.cabal b/relational-query.cabal
--- a/relational-query.cabal
+++ b/relational-query.cabal
@@ -1,5 +1,5 @@
 name:                relational-query
-version:             0.8.6.0
+version:             0.8.7.0
 synopsis:            Typeful, Modular, Relational, algebraic query engine
 description:         This package contiains typeful relation structure and
                      relational-algebraic query building DSL which can
diff --git a/src/Database/Relational/Query.hs b/src/Database/Relational/Query.hs
--- a/src/Database/Relational/Query.hs
+++ b/src/Database/Relational/Query.hs
@@ -53,7 +53,7 @@
 import Database.Relational.Query.Component
   (NameConfig (..), SchemaNameMode (..), ProductUnitSupport (..), IdentifierQuotation (..),
    Config (..), defaultConfig,
-   AggregateKey, Order (..))
+   AggregateKey, Order (..), Nulls (..))
 import Database.Relational.Query.Sub (SubQuery, unitSQL, queryWidth)
 import Database.Relational.Query.Projection (Projection, list)
 import Database.Relational.Query.Projectable
@@ -67,7 +67,7 @@
    distinct, all', on)
 import Database.Relational.Query.Monad.Trans.Aggregating
   (key, key', set, bkey, rollup, cube, groupingSets)
-import Database.Relational.Query.Monad.Trans.Ordering (orderBy, asc, desc)
+import Database.Relational.Query.Monad.Trans.Ordering (orderBy', orderBy, asc, desc)
 import Database.Relational.Query.Monad.Trans.Assigning (assignTo, (<-#))
 import Database.Relational.Query.Monad.BaseType
 import Database.Relational.Query.Monad.Type
diff --git a/src/Database/Relational/Query/Arrow.hs b/src/Database/Relational/Query/Arrow.hs
--- a/src/Database/Relational/Query/Arrow.hs
+++ b/src/Database/Relational/Query/Arrow.hs
@@ -41,7 +41,7 @@
 
   groupBy', key, key', set, bkey, rollup, cube, groupingSets,
 
-  orderBy, asc, desc,
+  orderBy', orderBy, asc, desc,
 
   partitionBy, over,
 
@@ -75,7 +75,7 @@
    on, wheres, having, groupBy, placeholder,
    relation, relation', aggregateRelation, aggregateRelation', uniqueRelation',
    groupBy', key, key', set, bkey, rollup, cube, groupingSets,
-   orderBy, asc, desc, partitionBy, over,
+   orderBy', orderBy, asc, desc, partitionBy, over,
    derivedUpdate', derivedUpdate,
    derivedInsertValue', derivedInsertValue,
    derivedDelete', derivedDelete,
@@ -369,6 +369,14 @@
 --   Finalize locally built 'AggregatingSetList'.
 groupingSets :: AggregatingSetList () a -> AggregateKey a
 groupingSets = runAofM Monadic.groupingSets
+
+-- | Same as 'Monadic.orderBy''.
+--   The result arrow is designed to be injected by local projections.
+orderBy' :: Monad m
+         => Order
+         -> Nulls
+         -> Orderings c m (Projection c t) ()
+orderBy' o n = queryA $ \p -> Monadic.orderBy' p o n
 
 -- | Same as 'Monadic.orderBy'.
 --   The result arrow is designed to be injected by local projections.
diff --git a/src/Database/Relational/Query/Component.hs b/src/Database/Relational/Query/Component.hs
--- a/src/Database/Relational/Query/Component.hs
+++ b/src/Database/Relational/Query/Component.hs
@@ -16,12 +16,12 @@
          AggregateKey,
 
          -- * Types for ordering
-         Order (..),
+         Order (..), Nulls (..),
        ) where
 
 import Database.Relational.Query.Internal.Config
   (NameConfig (..),
    ProductUnitSupport (..), SchemaNameMode (..), IdentifierQuotation (..),
    Config (..), defaultConfig,)
-import Database.Relational.Query.Internal.BaseSQL (Order (..),)
+import Database.Relational.Query.Internal.BaseSQL (Order (..), Nulls (..),)
 import Database.Relational.Query.Internal.GroupingSQL (AggregateKey)
diff --git a/src/Database/Relational/Query/Internal/BaseSQL.hs b/src/Database/Relational/Query/Internal/BaseSQL.hs
--- a/src/Database/Relational/Query/Internal/BaseSQL.hs
+++ b/src/Database/Relational/Query/Internal/BaseSQL.hs
@@ -10,7 +10,7 @@
 -- This module provides base structure of SQL syntax tree.
 module Database.Relational.Query.Internal.BaseSQL (
   Duplication (..), showsDuplication,
-  Order (..), OrderColumn, OrderingTerm, composeOrderBy,
+  Order (..), Nulls (..), OrderColumn, OrderingTerm, composeOrderBy,
   AssignColumn, AssignTerm, Assignment, composeSets,
   composeChunkValues, composeChunkValuesWithColumns,
   ) where
@@ -37,21 +37,25 @@
 -- | Order direction. Ascendant or Descendant.
 data Order = Asc | Desc  deriving Show
 
+-- | Order of null.
+data Nulls =  NullsFirst | NullsLast deriving Show
+
 -- | Type for order-by column
 type OrderColumn = StringSQL
 
 -- | Type for order-by term
-type OrderingTerm = (Order, OrderColumn)
+type OrderingTerm = ((Order, Maybe Nulls), OrderColumn)
 
 -- | Compose ORDER BY clause from OrderingTerms
 composeOrderBy :: [OrderingTerm] -> StringSQL
 composeOrderBy =  d where
   d []       = mempty
   d ts@(_:_) = ORDER <> BY <> SQL.fold (|*|) (map showsOt ts)
-  showsOt (o, e) = e <> order o
+  showsOt ((o, mn), e) = e <> order o <> maybe mempty ((NULLS <>) . nulls) mn
   order Asc  = ASC
   order Desc = DESC
-
+  nulls NullsFirst = FIRST
+  nulls NullsLast  = LAST
 
 -- | Column SQL String of assignment
 type AssignColumn = StringSQL
diff --git a/src/Database/Relational/Query/Monad/Trans/Ordering.hs b/src/Database/Relational/Query/Monad/Trans/Ordering.hs
--- a/src/Database/Relational/Query/Monad/Trans/Ordering.hs
+++ b/src/Database/Relational/Query/Monad/Trans/Ordering.hs
@@ -19,7 +19,7 @@
   Orderings, orderings,
 
   -- * API of query with ordering
-  orderBy, asc, desc,
+  orderBy', orderBy, asc, desc,
 
   -- * Result
   extractOrderingTerms
@@ -32,7 +32,7 @@
 import Data.DList (DList, toList)
 
 import Database.Relational.Query.Internal.BaseSQL
-  (Order(Asc, Desc), OrderColumn, OrderingTerm)
+  (Order (..), Nulls (..), OrderColumn, OrderingTerm)
 
 import Database.Relational.Query.Projection (Projection)
 import qualified Database.Relational.Query.Projection as Projection
@@ -84,30 +84,38 @@
 
 -- | Add ordering terms.
 updateOrderBys :: (Monad m, ProjectableOrdering (Projection c))
-               => Order            -- ^ Order direction
-               -> Projection c t   -- ^ Ordering terms to add
-               -> Orderings c m () -- ^ Result context with ordering
-updateOrderBys order p = Orderings . mapM_ tell $ terms  where
-  terms = curry pure order `map` orderTerms p
+               => (Order, Maybe Nulls) -- ^ Order direction
+               -> Projection c t       -- ^ Ordering terms to add
+               -> Orderings c m ()     -- ^ Result context with ordering
+updateOrderBys opair p = Orderings . mapM_ tell $ terms  where
+  terms = curry pure opair `map` orderTerms p
 
+-- | Add ordering terms with null ordering.
+orderBy' :: (Monad m, ProjectableOrdering (Projection c))
+         => Projection c t   -- ^ Ordering terms to add
+         -> Order            -- ^ Order direction
+         -> Nulls            -- ^ Order of null
+         -> Orderings c m () -- ^ Result context with ordering
+orderBy' p o n = updateOrderBys (o, Just n) p
+
 -- | Add ordering terms.
 orderBy :: (Monad m, ProjectableOrdering (Projection c))
         => Projection c t   -- ^ Ordering terms to add
-        -> Order            -- ^ Order direction
+        -> Order        -- ^ Order direction
         -> Orderings c m () -- ^ Result context with ordering
-orderBy = flip updateOrderBys
+orderBy p o = updateOrderBys (o, Nothing) p
 
 -- | Add ascendant ordering term.
 asc :: (Monad m, ProjectableOrdering (Projection c))
     => Projection c t   -- ^ Ordering terms to add
     -> Orderings c m () -- ^ Result context with ordering
-asc  =  updateOrderBys Asc
+asc  =  updateOrderBys (Asc, Nothing)
 
 -- | Add descendant ordering term.
 desc :: (Monad m, ProjectableOrdering (Projection c))
      => Projection c t   -- ^ Ordering terms to add
      -> Orderings c m () -- ^ Result context with ordering
-desc =  updateOrderBys Desc
+desc =  updateOrderBys (Desc, Nothing)
 
 -- | Run 'Orderings' to get 'OrderingTerms'
 extractOrderingTerms :: (Monad m, Functor m) => Orderings c m a -> m (a, [OrderingTerm])
diff --git a/test/sqlsEq.hs b/test/sqlsEq.hs
--- a/test/sqlsEq.hs
+++ b/test/sqlsEq.hs
@@ -506,17 +506,28 @@
   on $ just (a ! strA2') .=. b ?! strB2'
 
   orderBy (a ! strA1') Asc
-  orderBy (b ?! mayStrB1') Desc
+  orderBy' (b ?! mayStrB1') Desc NullsLast
 
   return $ (,) |$| a |*| b
 
+ordFlatY :: Relation () (SetA, Maybe SetB)
+ordFlatY =  relation $ do
+  a <- query setA
+  b <- queryMaybe setB
+  on $ just (a ! strA2') .=. b ?! strB2'
+
+  orderBy (a ! strA1') Asc
+  orderBy' b Desc NullsLast
+
+  return $ (,) |$| a |*| b
+
 ordAggX :: Relation () (String, Int64)
 ordAggX =  aggregateRelation $ do
   c <- query setC
 
   gc1 <- groupBy $ c ! strC1'
 
-  orderBy (sum' $ c ! intC0') Asc
+  orderBy' (sum' $ c ! intC0') Asc NullsFirst
 
   return $ gc1 >< count (c ! intC0')
 
@@ -529,10 +540,16 @@
     "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \
     \           T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \
     \  FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a2 = T1.str_b2) \
-    \  ORDER BY T0.str_a1 ASC, T1.may_str_b1 DESC"
+    \  ORDER BY T0.str_a1 ASC, T1.may_str_b1 DESC NULLS LAST"
+  , eqProp "order-by - flag 2" ordFlatY
+    "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \
+    \           T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \
+    \  FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a2 = T1.str_b2) \
+    \  ORDER BY T0.str_a1 ASC, T1.int_b0 DESC NULLS LAST, \
+    \           T1.may_str_b1 DESC NULLS LAST, T1.str_b2 DESC NULLS LAST"
   , eqProp "order-by - aggregated" ordAggX
     "SELECT ALL T0.str_c1 AS f0, COUNT(T0.int_c0) AS f1 \
-    \  FROM TEST.set_c T0 GROUP BY T0.str_c1 ORDER BY SUM(T0.int_c0) ASC"
+    \  FROM TEST.set_c T0 GROUP BY T0.str_c1 ORDER BY SUM(T0.int_c0) ASC NULLS FIRST"
   ]
 
 partitionX :: Relation () (String, Int64)
diff --git a/test/sqlsEqArrow.hs b/test/sqlsEqArrow.hs
--- a/test/sqlsEqArrow.hs
+++ b/test/sqlsEqArrow.hs
@@ -416,17 +416,28 @@
   on -< just (a ! strA2') .=. b ?! strB2'
 
   orderBy Asc  -< a ! strA1'
-  orderBy Desc -< b ?! mayStrB1'
+  orderBy' Desc NullsLast -< b ?! mayStrB1'
 
   returnA -< (,) |$| a |*| b
 
+ordFlatY :: Relation () (SetA, Maybe SetB)
+ordFlatY =  relation $ proc () -> do
+  a <- query setA -< ()
+  b <- queryMaybe setB -< ()
+  on -< just (a ! strA2') .=. b ?! strB2'
+
+  orderBy Asc  -< a ! strA1'
+  orderBy' Desc NullsLast -< b
+
+  returnA -< (,) |$| a |*| b
+
 ordAggX :: Relation () (String, Int64)
 ordAggX =  aggregateRelation $ proc () -> do
   c <- query setC -< ()
 
   gc1 <- groupBy -< c ! strC1'
 
-  orderBy Asc -< sum' $ c ! intC0'
+  orderBy' Asc NullsFirst -< sum' $ c ! intC0'
 
   returnA -< gc1 >< count (c ! intC0')
 
@@ -439,10 +450,16 @@
     "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \
     \           T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \
     \  FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a2 = T1.str_b2) \
-    \  ORDER BY T0.str_a1 ASC, T1.may_str_b1 DESC"
+    \  ORDER BY T0.str_a1 ASC, T1.may_str_b1 DESC NULLS LAST"
+  , eqProp "order-by - flat 2" ordFlatY
+    "SELECT ALL T0.int_a0 AS f0, T0.str_a1 AS f1, T0.str_a2 AS f2, \
+    \           T1.int_b0 AS f3, T1.may_str_b1 AS f4, T1.str_b2 AS f5 \
+    \  FROM TEST.set_a T0 LEFT JOIN TEST.set_b T1 ON (T0.str_a2 = T1.str_b2) \
+    \  ORDER BY T0.str_a1 ASC, T1.int_b0 DESC NULLS LAST, \
+    \           T1.may_str_b1 DESC NULLS LAST, T1.str_b2 DESC NULLS LAST"
   , eqProp "order-by - aggregated" ordAggX
     "SELECT ALL T0.str_c1 AS f0, COUNT(T0.int_c0) AS f1 \
-    \  FROM TEST.set_c T0 GROUP BY T0.str_c1 ORDER BY SUM(T0.int_c0) ASC"
+    \  FROM TEST.set_c T0 GROUP BY T0.str_c1 ORDER BY SUM(T0.int_c0) ASC NULLS FIRST"
   ]
 
 partitionX :: Relation () (String, Int64)
