📄 mssql.php
字号:
* * @param boolean $check indicates whether the function should just check if the DBMS driver * can perform the requested table alterations if the value is true or * actually perform them otherwise. * * @return mixed MDB2_OK on success, a MDB2 error on failure * @access public */ function alterTable($name, $changes, $check) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } $name_quoted = $db->quoteIdentifier($name, true); foreach ($changes as $change_name => $change) { switch ($change_name) { case 'remove': case 'rename': case 'add': case 'change': case 'name': break; default: return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null, 'change type "'.$change_name.'" not yet supported', __FUNCTION__); } } if ($check) { return MDB2_OK; } $idxname_format = $db->getOption('idxname_format'); $db->setOption('idxname_format', '%s'); if (!empty($changes['remove']) && is_array($changes['remove'])) { $result = $this->_dropConflictingIndices($name, array_keys($changes['remove'])); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } $result = $this->_dropConflictingConstraints($name, array_keys($changes['remove'])); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } $query = ''; foreach ($changes['remove'] as $field_name => $field) { if ($query) { $query.= ', '; } $field_name = $db->quoteIdentifier($field_name, true); $query.= 'COLUMN ' . $field_name; } $result = $db->exec("ALTER TABLE $name_quoted DROP $query"); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } } if (!empty($changes['rename']) && is_array($changes['rename'])) { foreach ($changes['rename'] as $field_name => $field) { $field_name = $db->quoteIdentifier($field_name, true); $result = $db->exec("sp_rename '$name_quoted.$field_name', '".$field['name']."', 'COLUMN'"); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } } } if (!empty($changes['add']) && is_array($changes['add'])) { $query = ''; foreach ($changes['add'] as $field_name => $field) { if ($query) { $query.= ', '; } else { $query.= 'ADD '; } $query.= $db->getDeclaration($field['type'], $field_name, $field); } $result = $db->exec("ALTER TABLE $name_quoted $query"); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } } $dropped_indices = array(); $dropped_constraints = array(); if (!empty($changes['change']) && is_array($changes['change'])) { $dropped = $this->_dropConflictingIndices($name, array_keys($changes['change'])); if (PEAR::isError($dropped)) { $db->setOption('idxname_format', $idxname_format); return $dropped; } $dropped_indices = array_merge($dropped_indices, $dropped); $dropped = $this->_dropConflictingConstraints($name, array_keys($changes['change'])); if (PEAR::isError($dropped)) { $db->setOption('idxname_format', $idxname_format); return $dropped; } $dropped_constraints = array_merge($dropped_constraints, $dropped); foreach ($changes['change'] as $field_name => $field) { //MSSQL doesn't allow multiple ALTER COLUMNs in one query $query = 'ALTER COLUMN '; //MSSQL doesn't allow changing the DEFAULT value of a field in altering mode if (array_key_exists('default', $field['definition'])) { unset($field['definition']['default']); } $query .= $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']); $result = $db->exec("ALTER TABLE $name_quoted $query"); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } } } // restore the dropped conflicting indices and constraints foreach ($dropped_indices as $index_name => $index) { $result = $this->createIndex($name, $index_name, $index); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } } foreach ($dropped_constraints as $constraint_name => $constraint) { $result = $this->createConstraint($name, $constraint_name, $constraint); if (PEAR::isError($result)) { $db->setOption('idxname_format', $idxname_format); return $result; } } $db->setOption('idxname_format', $idxname_format); if (!empty($changes['name'])) { $new_name = $db->quoteIdentifier($changes['name'], true); $result = $db->exec("sp_rename '$name_quoted', '$new_name'"); if (PEAR::isError($result)) { return $result; } } return MDB2_OK; } // }}} // {{{ _dropConflictingIndices() /** * Drop the indices that prevent a successful ALTER TABLE action * * @param string $table table name * @param array $fields array of names of the fields affected by the change * * @return array dropped indices definitions */ function _dropConflictingIndices($table, $fields) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } $dropped = array(); $index_names = $this->listTableIndexes($table); if (PEAR::isError($index_names)) { return $index_names; } $db->loadModule('Reverse'); $indexes = array(); foreach ($index_names as $index_name) { $idx_def = $db->reverse->getTableIndexDefinition($table, $index_name); if (!PEAR::isError($idx_def)) { $indexes[$index_name] = $idx_def; } } foreach ($fields as $field_name) { foreach ($indexes as $index_name => $index) { if (!isset($dropped[$index_name]) && array_key_exists($field_name, $index['fields'])) { $dropped[$index_name] = $index; $result = $this->dropIndex($table, $index_name); if (PEAR::isError($result)) { return $result; } } } } return $dropped; } // }}} // {{{ _dropConflictingConstraints() /** * Drop the constraints that prevent a successful ALTER TABLE action * * @param string $table table name * @param array $fields array of names of the fields affected by the change * * @return array dropped constraints definitions */ function _dropConflictingConstraints($table, $fields) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } $dropped = array(); $constraint_names = $this->listTableConstraints($table); if (PEAR::isError($constraint_names)) { return $constraint_names; } $db->loadModule('Reverse'); $constraints = array(); foreach ($constraint_names as $constraint_name) { $cons_def = $db->reverse->getTableConstraintDefinition($table, $constraint_name); if (!PEAR::isError($cons_def)) { $constraints[$constraint_name] = $cons_def; } } foreach ($fields as $field_name) { foreach ($constraints as $constraint_name => $constraint) { if (!isset($dropped[$constraint_name]) && array_key_exists($field_name, $constraint['fields'])) { $dropped[$constraint_name] = $constraint; $result = $this->dropConstraint($table, $constraint_name); if (PEAR::isError($result)) { return $result; } } } // also drop implicit DEFAULT constraints $default = $this->_getTableFieldDefaultConstraint($table, $field_name); if (!PEAR::isError($default) && !empty($default)) { $result = $this->dropConstraint($table, $default); if (PEAR::isError($result)) { return $result; } } } return $dropped; } // }}} // {{{ _getTableFieldDefaultConstraint() /** * Get the default constraint for a table field * * @param string $table name of table that should be used in method * @param string $field name of field that should be used in method * * @return mixed name of default constraint on success, a MDB2 error on failure * @access private */ function _getTableFieldDefaultConstraint($table, $field) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } $table = $db->quoteIdentifier($table, true); $field = $db->quote($field, 'text'); $query = "SELECT OBJECT_NAME(syscolumns.cdefault) FROM syscolumns WHERE syscolumns.id = object_id('$table') AND syscolumns.name = $field AND syscolumns.cdefault <> 0"; return $db->queryOne($query); } // }}} // {{{ listTables() /** * list all tables in the current database * * @return mixed array of table names on success, a MDB2 error on failure * @access public */ function listTables() { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } $query = 'EXEC sp_tables @table_type = "\'TABLE\'"'; $table_names = $db->queryCol($query, null, 2); if (PEAR::isError($table_names)) { return $table_names; } $result = array(); foreach ($table_names as $table_name) { if (!$this->_fixSequenceName($table_name, true)) { $result[] = $table_name; } } if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result); } return $result; } // }}} // {{{ listTableFields() /** * list all fields in a table in the current database * * @param string $table name of table that should be used in method * * @return mixed array of field names on success, a MDB2 error on failure * @access public */ function listTableFields($table) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } $table = $db->quoteIdentifier($table, true); $columns = $db->queryCol("SELECT c.name FROM syscolumns c LEFT JOIN sysobjects o ON c.id = o.id WHERE o.name = '$table'"); if (PEAR::isError($columns)) { return $columns; } if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { $columns = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $columns); } return $columns; } // }}} // {{{ listTableIndexes() /** * list all indexes in a table * * @param string $table name of table that should be used in method * * @return mixed array of index names on success, a MDB2 error on failure * @access public */ function listTableIndexes($table) { $db =& $this->getDBInstance(); if (PEAR::isError($db)) { return $db; } $key_name = 'INDEX_NAME'; $pk_name = 'PK_NAME'; if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) { if ($db->options['field_case'] == CASE_LOWER) { $key_name = strtolower($key_name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -