diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,11 @@
 # Revision history for Selda
 
 
+## 0.3.1.0 -- 2018-08-06
+
+* Minor API fix when defining table attributes.
+
+
 ## 0.3.0.0 -- 2018-08-05
 
 * Support for Stack and GHC 8.4.
diff --git a/selda.cabal b/selda.cabal
--- a/selda.cabal
+++ b/selda.cabal
@@ -1,5 +1,5 @@
 name:                selda
-version:             0.3.0.0
+version:             0.3.1.0
 synopsis:            Multi-backend, high-level EDSL for interacting with SQL databases.
 description:         This package provides an EDSL for writing portable, type-safe, high-level
                      database code. Its feature set includes querying and modifying databases,
diff --git a/src/Database/Selda/Generic.hs b/src/Database/Selda/Generic.hs
--- a/src/Database/Selda/Generic.hs
+++ b/src/Database/Selda/Generic.hs
@@ -6,7 +6,7 @@
 -- | Generics utilities.
 module Database.Selda.Generic
   ( Relational, Generic
-  , tblCols, mkDummy, identify, params, def, gNew
+  , tblCols, params, def, gNew
   ) where
 import Control.Monad.State
 import Data.Dynamic
@@ -20,7 +20,6 @@
 import qualified GHC.TypeLits as TL
 import qualified GHC.Generics as G ((:+:)(..))
 #endif
-import Unsafe.Coerce
 import Control.Exception (Exception (..), try, throw)
 import System.IO.Unsafe
 import Database.Selda.Types
@@ -49,18 +48,6 @@
   , GSelectors a (Rep a)
   )
 
--- | A dummy of some type. Encapsulated to avoid improper use, since all of
---   its fields are 'unsafeCoerce'd ints.
-newtype Dummy a = Dummy a
-
--- | Create a dummy of the given type.
-mkDummy :: (Generic a, GRelation (Rep a)) => Dummy a
-mkDummy = Dummy $ to $ evalState gMkDummy 0
-
--- | Get the selector identifier of the given selector for the given dummy.
-identify :: Dummy a -> (a -> b) -> Int
-identify (Dummy d) f = unsafeCoerce $ f d
-
 -- | Extract all insert parameters from a generic value.
 params :: Relational a => a -> [Either Param Param]
 params = unsafePerformIO . gParams . from
@@ -99,17 +86,12 @@
            -> (Int -> Maybe ColName -> ColName)
            -> State Int [ColInfo]
 
-  -- | Create a dummy value where all fields are replaced by @unsafeCoerce@'d
-  --   ints. See 'mkDummy' and 'identify' for more information.
-  gMkDummy :: State Int (f a)
-
   -- | Create a new value with all default fields.
   gNew :: Proxy f -> [UntypedCol sql]
 
 instance {-# OVERLAPPABLE #-} GRelation a => GRelation (M1 t c a) where
   gParams (M1 x) = gParams x
   gTblCols _ = gTblCols (Proxy :: Proxy a)
-  gMkDummy = M1 <$> gMkDummy
   gNew _ = gNew (Proxy :: Proxy a)
 
 instance {-# OVERLAPPING #-} (G.Selector c, GRelation a) =>
@@ -121,7 +103,6 @@
         case selName ((M1 undefined) :: M1 S c a b) of
           "" -> Nothing
           s  -> Just (mkColName $ pack s)
-  gMkDummy = M1 <$> gMkDummy
   gNew _ = gNew (Proxy :: Proxy a)
 
 instance (Typeable a, SqlType a) => GRelation (K1 i a) where
@@ -151,11 +132,6 @@
         | typeRepTyCon (typeRep (Proxy :: Proxy a)) == maybeTyCon = [Optional]
         | otherwise                                               = [Required]
 
-  gMkDummy = do
-    n <- get
-    put (n+1)
-    return $ unsafeCoerce n
-
   gNew _ = [Untyped (Lit (defaultValue :: Lit a))]
 
 instance (GRelation a, GRelation b) => GRelation (a G.:*: b) where
@@ -167,10 +143,6 @@
     where
       a = Proxy :: Proxy a
       b = Proxy :: Proxy b
-  gMkDummy = do
-    a <- gMkDummy :: State Int (a x)
-    b <- gMkDummy :: State Int (b x)
-    return (a G.:*: b)
   gNew _ = gNew (Proxy :: Proxy a) ++ gNew (Proxy :: Proxy b)
 
 #if MIN_VERSION_base(4, 9, 0)
@@ -182,7 +154,6 @@
     )) => GRelation (a G.:+: b) where
   gParams = error "unreachable"
   gTblCols = error "unreachable"
-  gMkDummy = error "unreachable"
   gNew = error "unreachable"
 
 instance {-# OVERLAPS #-}
@@ -193,6 +164,5 @@
     )) => GRelation (K1 i (C.Col s a)) where
   gParams = error "unreachable"
   gTblCols = error "unreachable"
-  gMkDummy = error "unreachable"
   gNew = error "unreachable"
 #endif
diff --git a/src/Database/Selda/Selectors.hs b/src/Database/Selda/Selectors.hs
--- a/src/Database/Selda/Selectors.hs
+++ b/src/Database/Selda/Selectors.hs
@@ -5,9 +5,10 @@
 module Database.Selda.Selectors
   ( Assignment ((:=)), Selected, Selector, Source, Selectors, GSelectors
   , (!), with, ($=)
-  , selectorsFor, selectorIndex
+  , selectorsFor, selectorIndex, unsafeSelector
   ) where
 import Control.Monad.State.Strict
+import Database.Selda.SqlRow (SqlRow)
 import Database.Selda.SqlType
 import Database.Selda.Types
 import Database.Selda.Column
@@ -29,6 +30,13 @@
 type family Source a where
   Source (Maybe a) = a
   Source a         = a
+
+-- | A selector indicating the nth (zero-based) column of a table.
+--
+--   Will cause errors in queries during compilation, execution, or both,
+--   unless handled with extreme care. You really shouldn't use it at all.
+unsafeSelector :: SqlRow a => Int -> Selector a b
+unsafeSelector = Selector
 
 -- | Extract the given column from the given row.
 --   Extracting a value from a nullable column will yield a nullable value.
diff --git a/src/Database/Selda/Table.hs b/src/Database/Selda/Table.hs
--- a/src/Database/Selda/Table.hs
+++ b/src/Database/Selda/Table.hs
@@ -30,7 +30,7 @@
 --   Essentially a pair or a record selector over the type @a@ and a column
 --   attribute.
 data Attr a where
-  (:-) :: (a -> b) -> Attribute a b -> Attr a
+  (:-) :: Selector a b -> Attribute a b -> Attr a
 
 -- | Generate a table from the given table name and list of column attributes.
 --   All @Maybe@ fields in the table's type will be represented by nullable
@@ -90,19 +90,18 @@
   , tableHasAutoPK = apk
   }
   where
-    dummy = mkDummy
     cols = zipWith addAttrs [0..] (tblCols (Proxy :: Proxy a) fieldMod)
     apk = or [AutoIncrement `elem` as | _ :- Attribute as <- attrs]
     addAttrs n ci = ci
       { colAttrs = colAttrs ci ++ concat
           [ as
-          | f :- Attribute as <- attrs
-          , identify dummy f == n
+          | sel :- Attribute as <- attrs
+          , selectorIndex sel == n
           ]
       , colFKs = colFKs ci ++
           [ thefk
-          | f :- ForeignKey thefk <- attrs
-          , identify dummy f == n
+          | sel :- ForeignKey thefk <- attrs
+          , selectorIndex sel == n
           ]
       }
 
diff --git a/src/Database/Selda/Unsafe.hs b/src/Database/Selda/Unsafe.hs
--- a/src/Database/Selda/Unsafe.hs
+++ b/src/Database/Selda/Unsafe.hs
@@ -6,9 +6,11 @@
   , aggr
   , cast
   , castAggr
+  , unsafeSelector
   ) where
 import Database.Selda.Column
 import Database.Selda.Inner (Aggr, aggr, liftAggr)
+import Database.Selda.Selectors (unsafeSelector)
 import Database.Selda.SqlType
 import Data.Text (Text)
 import Data.Proxy
