#NOT production ready!
Pribi (forked from Dibi - smart database layer for PHP)
Original Dibi is great.
Not the unified interface for any database vendor, but the fluent interface.
And short notations of standard operations.
And for type-check of parameters, inserted similarly to printf() (just for integer the %i notation is used in difference).
And should be greater, but the price for universality does not allow it. Especially lack of prepared statements hurts these developers, who recalculate CPU time to money.
Forbidden changes, because of final methods or whole classes, confound chance to extend Dibi itself, so fork has been enforced. All hail the "Fluent, MySQL, prepared statements". And wish me good luck with development.
Pribi requires PHP 5.5.0 or later because of namespaces 5.3, __callStatic() 5.3, __DIR__ 5.3, traits 5.4 and Foo::class magic (auto-existing) absolute class name constant 5.5.
Identifier quote
- Pribi is for MySQL. That's the trick. That means, the quotation is done by ` (tick).
Not SQL-99 standard by " (double quote), not MS SQL style by [ ] (brackets) or anything else. Only `ticks`.
Protection against empty array of values to search by
-
Empty
IN()condition will cause syntax error in MySQL, Pribi will replace it for you byFALSE /* IN(empty) */(becauseIN (NULL)isNULL, not false). -
Similarly
NOT IN()will cause syntax error, Pribi will replace it for you byNOT FALSE /* IN(empty) */(becauseNOT IN (NULL)isNULL, not true).
Aliasing
-
For alias, use
select('table_with_some_domain_name.columnWithNameReferencingToTableDomain')->as('prettyAliasWithBothTableAndColumnMeaning'). -
If you want try to use shorthand as
select('columnName prettyAlias'), that means two strings split by white space, you will have to wrap both identifiers like thisselect('`columnName` `prettyAlias`') -
Otherwise Pribi will wrap your string as single identifier:
'columnName prettyAlias'=`columnName prettyAlias`(yes, name with space is valid). -
So again, use fluent. Every time. That's what Pribi has been designed for and what is native then.
-
SELECT 1is complete and valid query, it will return, surprisingly,1. -
SELECT * FROM `tableFoo` INNER JOIN `tableBar`is valid too, but withoutON(orWHERE) condition, specifying bindings betweentableFooandtableBar, nothing will be as result. MySQL allows to run query like this (with empty result), but Pribi does not offer you (by fluent) execution of that query immediately afterINNER JOINbecause of useless result. -
SELECT IF(1, 'Hit!', 'Missed!') AS integerAsBooleanwill give string Hit!,SELECT IF('1', 'Hit!', 'Missed!') AS stringIntegerAsBooleanwill give string Hit!,SELECT IF('true', 'Hit!', 'Missed!') AS stringAsBooleanwill give string Miss!. How is this possible? Maybe because u think in PHP or similar language. MySQL tries cast everything in condition to boolean. Integer or float is not a problem, string with integer of float value is again not a problem, but everything else, as any text, is converted to false. Finally,SELECT IF('0.1false', 'Hit!', 'Missed!') AS stringStartingByIntegerAsBooleanwill give string Hit!, because MySQL reads it from left to right and casting the value to number, so at the end MySQL uses float 0.1 as condition value and that is considered as true. -
SELECT * FROM `foo` LEFT JOIN `bar`on the other hand is not valid for MySQL and you will get a syntax error. And again, Pribi does not offer you (by fluent) the execution of that query. -
SELECT * FROM `foo` INNER JOIN `bar` ON TRUEseems almost same like previous situation, but notice the trailingON TRUEcondition. It says join everything with everything and will give you every combination of all rows of both tables, which will result intonumber of rows of first tablemultiplynumber of rows of second tableof result rows. -
SELECT * FROM `foo` LEFT JOIN `bar` ON TRUEseems again almost same like previous situation, which will give you again combinations of every row of every table, but notice theLEFTkeyword, which covers situation when the second table is empty - then at least rows from the first table will be in result (extended by columns of the second table, but with NULL values everywhere, as any LEFT JOIN without condition match). -
This is valid identifier
`9[;,-/`, and this too`SELECT (_) AS REALY?!`, if you do not forgot `ticks`. Like this you can name your columns, tables, databases, aliases (all called identifier). But seriously, do not do it, if you do not like pain badly. -
NULLis not a standard value, it does not mean nothing but much more something like does not know. If you want to search forNULLvalue, you will have to useIS NULLorIS NOT NULLconstruction. Comparing any value withNULLresults intoNULL, because MySQL really does not know, whatNULLmeans against compared value. For example,15 = NULLisNULL,"" = NULL(empty string) isNULL,TRUE = NULLisNULLand finallyNULL = NULLis againNULL. Because, remember this, MySQL does not know what is meaning ofNULL, so comparing unknown value with unknown value has unknown result. For any details, try MySQL official pages. -
When we are talking about
NULL, remember thanNULLcan occurs during calculation and then "NULL-out" whole result, as for example could do divination by zero (SELECT (5 + 64 / 0 - 12) IS NULLresults into 1). -
IN ()is not a valid condition and causes a syntax error because of missing parameters ofINcondition. Using`columnFoo` IN (NULL)matches nothing, even if some of `columnFoo` value isNULL(which is very special, respective very unknown, as mentioned before). -
NOT IN (NULL)is always false, althoughIN (NULL)is false also. The negation doesn't work. Again, NULL is very special, respective very unknown, and the result is unknown also, which means false. -
`columnFoo` LIKE `columnBar`condition brings same results as`columnFoo` = `columnBar`, but is performed much slower because of lexical value comparison and also ignores keys. Try it in your sandbox and never after. I checked this for MyISAM and InnoDB engines. -
How to multiply values of a column? To sum numbers from one row, you can just simply sum them by plus sign
SELECT (`firstColumn` + `secondColumn` + `anotherColumn`) AS `sumResult`and to multiply them by star signSELECT (`firstColumn` * `secondColumn` * `anotherColumn`) AS `multiplicationResult`. To sum values from all rows, but single column, you can use built-in functionSELECT SUM(`columnWithValuesToSum`), but what if you need to multiply values from all rows, but single column? Now math come to help by logarithmSELECT EXP(SUM(LOG(`columnWithValuesToMultiply`))) AS `multiplied`. -
INcommand becomes much faster than repeatedWHEREfor a large amount of values. For details try Danil Zburivsky research and then Baron Schwartz simple answer about sorted values in theINlist. -
Duplicate key on update when creating a table? Yes, that is quite confusing message. Its correct meaning is The name of a key (index) you want to use is already in use for an existing table.
-
Queries too slow? Use the index, Luke!. And use the
EXPLAINto find out if an index is used at all. -
To use or not to use
PRIMARY KEYfor InnoDB table? As say Jeremy Cole Every table has a primary key, even if you do not want to (if thePRIMARY KEYis not explicitly specified, the first non-NULL unique key is used, and failing that, a 48-bit hidden Row ID field is automatically added), so create it by yourself to take control over it. -
What operation comes first to play? SQL operations order are as follows. Check the Ben Nadel blog for details.
- FROM clause
- WHERE clause
- GROUP BY clause
- HAVING clause
- SELECT clause
- ORDER BY clause