What do you mean by change the column? Do you want to change the data type to something else? String maybe?
Also, don't forget to install the doctrine/dbal package for column manipulation.
how change the column of a table of enum type? First i create the enum: $table->enum('ref', ['single', 'monthly', 'biannual', 'amount', 'other']);
I need add new values, i tried this but it did not work: $table->enum('ref', ['single', 'monthly', 'biannual', 'amount', 'other'])->change();
how solve it?
Obs.: my database is psql.
What do you mean by change the column? Do you want to change the data type to something else? String maybe?
Also, don't forget to install the doctrine/dbal package for column manipulation.
i need insert new options in the enum.
$table->enum('ref', ['single', 'monthly', 'biannual']);
i insert two new options: 'amount', 'other'
$table->enum('ref', ['single', 'monthly', 'biannual', 'amount', 'other'])->change();
the error:
[Doctrine\DBAL\DBALException]
Unknown column type "enum" requested. Any Doctrine type that you use has to
be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list
of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If thi
s error occurs during database introspection then you might have forgot to r
egister all database types for a Doctrine Type. Use AbstractPlatform#registe
rDoctrineTypeMapping() or have your custom types implement Type#getMappedDat
abaseTypes(). If the type name is empty you might have a problem with the ca
che or forgot some mapping information.
Did you try without change()? Just create a new migration and add the old items + the new items.
public function up()
{
Schema::table('table_name', function(Blueprint $table)
{
$table->enum('ref',['single', 'monthly', 'biannual', 'amount', 'other']);
});
}
http://laravel.com/docs/5.1/migrations#modifying-columns
Note: Renaming columns in a table with a enum column is not currently supported.
Thanks guys for answers.
Ruffles, Without "change()":
[Illuminate\Database\QueryException]
SQLSTATE[42701]: Duplicate column: 7 ERROR: column "ref" of relation "purc
hases" already exists (SQL: alter table "purchases" add column "ref" varcha
r(255) check ("ref" in ('single', 'monthly', 'biannual', 'amount', 'other')
) not null, add column "amount" smallint not null default '1')
pmall, i don't want renaming column.
Obs.: I cannot lose the data in database.
@allanolivei this code work for me. without losing my data
/* ALTER TABLE expenses
MODIFY COLUMN expense
enum('Petrol','Rent','Salary','Tea','Transport','Gas Bill')
NOT NULL DEFAULT 'Petrol'; */
require "dbconn.php";
function set_and_enum_values( &$conn, $table , $field )
{
$query = "SHOW COLUMNS FROM $table LIKE '$field'";
$result = mysqli_query( $conn, $query ) or die( 'Error getting Enum/Set field ' . mysqli_error() );
$row = mysqli_fetch_row($result);
if(stripos($row[1], 'enum') !== false || stripos($row[1], 'set') !== false) { $values = str_ireplace(array('enum(', 'set('), '', trim($row[1], ')')); $values = explode(',', $values); $values = array_map(function($str) { return trim($str, ''"'); }, $values); } return $values; } $options = set_and_enum_values($con, 'expenses', 'expense'); foreach($options as $option): $newEnum .= "'".$option."', " ?>
< ?php endforeach; $newValue = 'GOOD JOB'; $sql = "ALTER TABLE expenses MODIFY COLUMN expense enum($newEnum'$newValue') NOT NULL DEFAULT 'Petrol'"; if ($con->query($sql) === TRUE) { $message = 'updated'; } else { $message = 'ERROR'; //echo "Error: " . $sql . "" . $con->error; } echo $message; ?>
That's why I don't use enum type...
I cannot lose the data in database.
You just make a new enum column with the allowed values and then update the rows, and then drop the old enum column.
Create a new enum column with additional types, copy everything from the first column, drop it, and rename the new column.
jekinney, Now it's too late. I already used it. hehe
I found this in mysql:
DB::statement("ALTER TABLE purchases CHANGE ref ref ENUM('single', 'monthly', 'biannual', 'amount', 'other')");
but I can not find in psql.
@allanolivei Just saw this now... thanks man!
You would think by now there would be a solution available.
PostgreSQL 9.1 introduced ability to ALTER Enum types:
ALTER TYPE enum_type ADD VALUE 'new_value' BEFORE 'old_value';
ALTER TYPE enum_type ADD VALUE 'new_value' AFTER 'old_value';
So you should be able to do something like this:
DB:statement("ALTER TYPE ref ADD VALUE 'amount' AFTER 'biannual'");
DB:statement("ALTER TYPE ref ADD VALUE 'other' AFTER 'amount'");
Thanks guys.
I've been analyzing the enum in laravel and realised that he is a limited varchar by a constrain, so I can change the constrain without losing data from my database.
The answer to my problem is:
DB::statement("ALTER TABLE purchases DROP CONSTRAINT purchases_ref_check");
$types = ['single', 'monthly', 'biannual', 'amount', 'other'];
$result = join( ', ', array_map(function( $value ){ return sprintf("'%s'::character varying", $value); }, $types) );
DB::statement("ALTER TABLE purchases add CONSTRAINT purchases_ref_check CHECK (ref::text = ANY (ARRAY[$result]::text[]))");
as laravel documentaion says :
The following column types can not be "changed": char, double, enum, mediumInteger, timestamp, tinyInteger, ipAddress, json, jsonb, macAddress, mediumIncrements, morphs, nullableMorphs, nullableTimestamps, softDeletes, timeTz, timestampTz, timestamps, timestampsTz, unsignedMediumInteger, unsignedTinyInteger, uuid.
thus:
we should use some hacks to do it. run as raw query is not good practice ... because it may not work on all database engine that laravel works with.
solution :
you can rename enum column and create another column with original name with new schema you want and then copy old column data to new column and finally remove old column. (if you want to change old data you can do it in foreach)
NOTE: if your table is very large this solution is not very well but you can do it with chunk
here sample code:
as laravel documentaion says :
The following column types can not be "changed": char, double, enum, mediumInteger, timestamp, tinyInteger, ipAddress, json, jsonb, macAddress, mediumIncrements, morphs, nullableMorphs, nullableTimestamps, softDeletes, timeTz, timestampTz, timestamps, timestampsTz, unsignedMediumInteger, unsignedTinyInteger, uuid.
thus:
we should use some hacks to do it. run as raw query is not good practice ... because it may not work on all database engine that laravel works with.
solution :
you can rename enum column and create another column with original name with new schema you want and then copy old column data to new column and finally remove old column. (if you want to change old data you can do it in foreach)
NOTE: if your table is very large this solution is not very well but you can do it with chunk
here sample code:
Schema::table('table', function (Blueprint $table) {
$table->renameColumn('originalName','tmpName');
});
Schema::table('table', function (Blueprint $table) {
$table->enum('originalName',['item1','item2','item3','item3']);
});
$all=DB::table('table')->get();
foreach($all as $item)
{
DB::table('table')->where('id',$item['id'])->update(['originalName'=>$item['tmpName']]);
}
Schema::table('table', function (Blueprint $table) {
$table->dropColumn('tmpName');
});
@roboticsexpert What is Blueprint here? Actually i am new here. I don't what it would be in my code.
TypeError Argument 1 passed to App\Http\Controllers\Users\DepositController::App\Http\Controllers\Users{closure}() must be an instance of App\Http\Controllers\Users\Blueprint, instance of Illuminate\Database\Schema\Blueprint given, called in D:\wampp\www\paymoney\vendor\laravel\framework\src\Illuminate\Database\Schema\Blueprint.php on line 95
This is a solution:
$all=DB::table('table')->get();
Schema::table('table', function (Blueprint $table) {
$table->dropColumn('columnName');
});
Schema::table('table', function (Blueprint $table) {
$table->enum('columnName',['item1','item2','item3','item3']);
});
foreach($all as $item)
{
DB::table('table')->where('id',$item->id)->update(['columnName'=>$item->columnName]);
}
I think there is a better and more simple solution:
DB::statement("ALTER TABLE `table` CHANGE `column` `column` ENUM('item1', 'item2') default NULL;");
This change the existing enum, and leave the data as-is.
Only the following column types can be "changed": bigInteger, binary, boolean, date, dateTime, dateTimeTz, decimal, integer, json, longText, mediumText, smallInteger, string, text, time, unsignedBigInteger, unsignedInteger and unsignedSmallInteger. https://laravel.com/docs/5.8/migrations#modifying-columns
I stumbled over this problem with my Postgres and my solution is:
$values = DocumentType::values();
// Convert the values to a string for the SQL statement
$valuesList = implode("', '", $values);
// Remove the existing constraint
DB::statement('ALTER TABLE documents DROP CONSTRAINT IF EXISTS documents_type_check;');
// Add the new constraint with the additional value
DB::statement("ALTER TABLE documents ADD CONSTRAINT documents_type_check CHECK ((type)::text = ANY (ARRAY['$valuesList']::text[]));");
For me It's working
Please or to participate in this conversation.