2013-05-13 7 views
1

Я использую следующий код, чтобы проверить, существует ли столбец, когда он не создается.Проверка наличия столбца в таблице базы данных

<cfquery name="qSelect" datasource="#dbname#"> 
    select Top 0 * from Elements 
</cfquery> 

<cfif not ListFindNoCase(qSelect.columnlist,"idLang")> 
    <cfquery name="qAlterTable" datasource="#dbname#" dbtype="ODBC"> 
     ALTER TABLE Elements ADD idLang varchar(200) NULL 
    </cfquery> 
</cfif> 

Может кто-нибудь предложить, если есть лучший способ сделать это?

+0

Не так, как я бы это сделать, но это выглядит, как он будет работать. Я предполагаю, что sql действителен для используемого вами механизма базы данных. –

+0

Какое программное обеспечение для баз данных вы используете? –

+0

Если вы делаете это как однократное задание, потому что это единственный способ получить доступ к вашему db, просто запустите запрос alter table. Если столбец есть, ошибка не имеет значения. Если это часть какого-либо приложения, возможно, вам следует отступить и подумать об этом. Мне кажется неразумным. –

ответ

2

Я бы запросил information_schema напрямую.

SELECT COLUMN_NAME 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'YourTableName' 
AND COLUMN_NAME = 'idLang' 

Если вы проверяете несколько имен столбцов можно изменить = к IN, а затем выполнять те же проверки, что вы делаете сейчас (listFindNoCASE). Я не знаю, что в любом случае это будет быстрее/лучше, но я так и сделаю.

Вы не указали СУБД, но это будет работать для SQL Server и MySQL

+0

Метод в вопросе получает тот же ответ с меньшим количеством работы. –

+1

* Если вы проверяете несколько имен столбцов * Простое, чтобы изменить '=' на предложение 'IN'. Затем проверьте, что query.recordCount равно длине списка. – Leigh

1

ответ Мэтта лучше.

Если вы не хотите, чтобы проверить первый или вы используете удивительный DB, как JET, вы также можете просто обернуть запрос в <cftry> теги

<cftry> 
    <cfquery name="qAlterTable" datasource="#dbname#" dbtype="ODBC"> 
     ALTER TABLE 
      Elements 
     ADD idLang varchar(200) NULL 
    </cfquery> 
    <cfcatch type = "database"> 
     <cfoutput>#cfcatch.message# - #cfcatch.details#</cfoutput> 
    </cfcatch> 
</try> 
+0

Мне нравится этот ответ лучше, чем у Мэтта. –

2

Если у вас есть ColdFusion 8+, лучший способ использовать <cfdbinfo>. Затем вы можете использовать его с любой базой данных.

<cfdbinfo datasource="votethisway.com" name="myColumns" type="columns" table="tblPoll" pattern="idLang"> 
<cfdump var="#myColumns#" label="myColumns"> 

<cfdbinfo> возвращает объект запроса, который содержит всю информацию о каждом столбце в таблице. Атрибут pattern может использоваться как фильтр для уменьшения результатов только для столбца, который вы тестируете.

Вот <cffunction>, который оборачивает его в красивую упаковку:

<cffunction access="public" name="tableColumnExists" output="no" returntype="boolean" description="returns true if a table column exists" verifyclient="no" securejson="false"> 
    <cfargument name="datasource" type="string" required="yes" hint="name of the datasource"> 
    <cfargument name="table" type="string" required="yes" hint="name of the table"> 
    <cfargument name="column" type="string" required="yes" hint="name of the column"> 

    <!---initialize private variables---> 
    <cfset var local = StructNew()> 

    <cftry> 
     <cfdbinfo datasource="#arguments.datasource#" name="local.qryColumns" type="columns" table="#arguments.table#" pattern="#arguments.column#"> 
     <cfcatch type="Database"> 
      <cfreturn false> 
     </cfcatch> 
    </cftry> 

    <cfif local.qryColumns.RecordCount> 
     <cfreturn true> 
    </cfif> 
    <cfreturn false> 
</cffunction> 
+0

Оба cfdbinfo и запрос таблиц метаданных будут работать напрямую. Так что «лучший» относительный ;-) Однако 'cfdbinfo' более портативен (если это фактор). – Leigh

0

Итак, я последовал каждое предложение в этом диалоге, и каждый из них был другой орех, чтобы связать. Затем я провел еще 3 часа в Интернете и до сих пор не придумал ПРОСТОЕ РЕШЕНИЕ к этой проблеме.

Зная, что coldfusion является простым серверным языком, я знаю, что где-то был какой-то ответ, поэтому я попробовал функцию «columnList». Удивительно, но это сработало:


<cfquery name="my_Recordset" datasource="my_Datasource"> 
    SELECT * FROM my_Table 
</cfquery> 

<CFIF NOT ISDEFINED('my_Recordset.my_Column')> 
    <!--- create column because it doesnt exist ---> 
<cfelse> 
    <!--- drop or update column because it exist ---> 
</cfif> 

Кроме того, вы можете поместить все столбцы в таблице в списке, вы можете выполнить поиск с помощью функции Список, ListContains, как показано ниже:


<cfquery name="my_Recordset" datasource="my_Datasource"> 
    SELECT * FROM my_Table 
</cfquery> 

<cfset myList = #my_Recordset.columnList#> 

<cfset mySearchResult = #ListContains(myList, "my_Column")#> 

<CFIF mySearchResult is 0> 
    <!--- create column because it doesnt exist ---> 
<cfelse> 
    <!--- drop or update column because it exist ---> 
</cfif> 

+0

Это лишь незначительная вариация на нескольких подходах, упомянутых уже, и с уважением, это не лучший подход. Большинство баз данных предприятий предоставляют более эффективные варианты идентификации существующих столбцов через представления [information_schema] (https://en.wikipedia.org/wiki/Information_schema). Если по какой-то причине ваша база данных не поддерживает эти представления или что-то подобное, по крайней мере, добавьте предложение 'where 1 = 0'. В противном случае запрос вернет каждую запись в таблице, что является пустой тратой полосы пропускания, поскольку данные никогда не используются. Обратите внимание, что ни один из вышеупомянутых значков фунта не требуется. – Leigh

Смежные вопросы